簡體   English   中英

類實例變量的對象方法鏈接的Python方法

[英]Python way for object method chaining for class instance variables

用例:

我有一個可以接收實例變量(表單域)的表單對象。 現在,我想使用方法鏈接來驗證那里的變量。 具有任意方法的示例:

class Field(object):

    def __init__(self, form, name):
        self.form = form
        self.name = name

    def unspace(self):
        setattr(self.form, self.name, getattr(self.form, self.name).replace(' ',''))
        return self

    def len_valid(self, length):
        if len(getattr(self.form, self.name)) < length :
            setattr(self.form, self.name + '_invalid', True)
            self.form.valid = False
        return self

class Forms(object):                                                                                    

    def __init__(self):
        self.valid = True

    def validate(self, name):
        return Field(self,name)

f = Forms()         # create the form with some data
f.a = 'J o Hn '
f.b = ' Too   L o n g'

f.validate('a').unspace().len_valid(2)  
f.validate('b').unspace().len_valid(5)  

RESULT :
f.a : 'JoHn'
f.a_invalid : True
f.b : 'TooLong'
f.valid : False

這是在Form實例變量上創建方法鏈接的Python方式。

是的,沒有。

鏈接方法調用的Pythonic方式正是您編寫的內容:

f.validate('a').unspace().len_valid(2)  

但是,除非需要,否則動態訪問屬性的Python方式就是不要這樣做。 如果將表單變量存儲在dict而不是作為對象的實例變量存儲,那么一切將變得更加簡單和可讀。

即使您確實確實需要使用fa而不是f['a']來訪問形式變量(例如,因為這是交互式外殼程序的一部分,或者某些第三方API要求),實際上編寫所有您的代碼也更容易圍繞dict編寫代碼,並使用您喜歡的AttrDict類(來自PyPI或ActiveState)為用戶/第三方API提供屬性樣式的訪問。

同樣,如果您使用某些方法進一步將Field對象更改為一個圍繞值的瑣碎包裝,而不是(實際上)是對父級和鍵的引用,它將更加簡單。

另外,如果您像a_invalid這樣a_invalid生成新屬性,則可能希望始終生成它們,而不僅是在它們為真時。 否則,檢查a是否有效看起來像這樣:

try:
    avalid = not f.a_invalid
except NameError:
    avalid = True

令人費解的是,但是如果您的呼叫者想避免這種情況,那么唯一的方法就是這樣:

avalid = not getattr(f, 'a_invalid', False)

首先,這似乎挫敗了為調用者偽造屬性的整個目的。

另外,請記住,必須確保永遠不會存在名稱以_invalid結尾的字段。 由於您可以將新屬性附加到Python中的幾乎所有內容上,因此,如果您確實確實想以這種方式進行所有操作,那么為什么要使用f.a_invalid而不是fainvalid呢?

自從您在注釋中詢問后,圍繞值的瑣碎包裝程序如下所示:

class Field(object):

    def __init__(self, value):
        self.value = value
        self.valid = True

    def unspace(self):
        self.value = self.value.replace(' ', '')
        return self

    def len_valid(self, length):
        if len(self.value) < length:
            self.valid = False
        return self

不必使每個字段都達到表單來設置其有效性,只需使表單執行此操作即可:

class Form(object):
    …
    def valid(self):
        return all(field.valid for field in self.fields)

而且,如果您確實需要使該valid外觀看起來像成員變量而不是方法,則只需使用@property

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM