2

ユースケース:

インスタンス変数(フォームフィールド)を受け取るフォームオブジェクトがあります。ここで、メソッドチェーンを使用して変数を検証するのが好きです。任意の方法の例:

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の方法ですか。

4

1 に答える 1

4

はいといいえ。

メソッド呼び出しをチェーンするPythonの方法は、まさにあなたが書いたものです。

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

しかし、属性に動的にアクセスするPythonの方法は、必要がない限り、そうしないことです。フォーム変数がdictオブジェクトのインスタンス変数としてではなくに格納されている場合、すべてがはるかに単純で読みやすくなります。

f.a代わりにフォーム変数にアクセスできるようにする必要がある場合でもf['a'](たとえば、これはインタラクティブシェルの一部であるため、または一部のサードパーティAPIで必要なため)、実際には、の周りにすべてのコードを記述してdictAttrDictユーザー/サードパーティAPIに属性スタイルのアクセスを提供するためのお気に入りのクラス(PyPIまたはActiveStateから)。

また、Fieldオブジェクトをさらにいくつかのメソッドを使用して値の簡単なラッパーになるように変更した場合、(実際には)親とキーへの参照ではなく、さらに簡単になります。

また、のようにその場で新しい属性を生成する場合は、それらがtrueである場合だけでなく、常にそれらを生成する必要があります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、たとえば、代わりに使用するのはなぜf.a.invalidですか?

コメントで質問したので、値の簡単なラッパーは次のようになります。

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ください。

于 2012-12-12T18:32:46.230 に答える