2016-11-12 13 views
3

私はPythonのメタプログラミングで少し演奏しています。インスタンス作成後に上書きされた__repr__

class FormMetaClass(type): 

    def __new__(cls, clsname, bases, methods): 
     # Attach attribute names to the descriptors 
     for key, value in methods.items(): 
      if isinstance(value, FieldDescriptor): 
       value.name = key 
     return type.__new__(cls, clsname, bases, methods) 


class Form(metaclass=FormMetaClass): 

    @classmethod 
    def from_json(cls, incoming): 
     instance = cls() 
     data = json.loads(incoming) 
     for k, v in data.items(): 
      if (not hasattr(instance, k)): 
       raise KeyError("Atrribute not found") 
      instance.__setattr__(k, v) 
     return cls 

class MyForm(Form): 

    first_name = String() 
    last_name = String() 
    age = Integer() 

    def __repr__(self): 
     return "{} {}".format(self.first_name, self.last_name) 


def main(): 
    data = json.dumps({'first_name': 'Thomas', 
         'last_name': 'Junk'}) 
    form = MyForm.from_json(data) 
    print(form) 

if __name__ == "__main__": 
    main() 

class FieldDescriptor: 

    def __init__(self, name=None, **opts): 
     self.name = name 
     for key, value in opts.items(): 
      setattr(self, key, value) 

    def __set__(self, instance, value): 
     instance.__dict__[self.name] = value 


class Typechecked(FieldDescriptor): 
    expected_type = type(None) 

    def __set__(self, instance, value): 
     if not isinstance(value, self.expected_type): 
      raise TypeError('expected ' + str(self.expected_type)) 
     super().__set__(instance, value) 


class Integer(Typechecked): 
    expected_type = int 


class String(Typechecked): 
    expected_type = str 

私はメタクラスFormMetaClassを持ってFormを持っています。 代わりのコンストラクタを使用するには、@classmethodを使用しています。 instanceを作成します。これはこれまでのところうまくいくようです。

__repr__(または__str__を同じ意味で使用しています)とは何も動作しません。 MyForm()でインスタンスを作成すると、すべて問題ありません。 @classmethod経由でインスタンスを作成すると、「デフォルト」の実装が行われます。

私は Thomas Junkを期待したが、私は

はあなたが私にヒントを与えることができる<class '__main__.MyForm'>を取得し、私が何を望むのですか?

+1

おそらく 'field.String()'と 'field.Integer()'オブジェクトは 'FieldDescriptor'インスタンスですか?私はあなたの問題を再現できるかどうかを確認しようとしていますが、これはそれらのオブジェクトが欠落している[mcve]ではありません。 –

+0

ディスクリプタが追加されました。 –

+1

私はディスクリプタなしで既にそれを再現することができます。 –

答えて

3

あなたはクラスではなく、新しく作成されたインスタンスを返すされています

return cls 

ですから、新しいインスタンスMyForm()は、あなただけですべての属性を設定し、MyFormを返しません。代わりにinstanceを返す、

>>> form is MyForm 
True 
>>> print(MyForm) 
<class '__main__.MyForm'> 

修正は簡単です::

@classmethod 
def from_json(cls, incoming): 
    instance = cls() 
    data = json.loads(incoming) 
    for k, v in data.items(): 
     if (not hasattr(instance, k)): 
      raise KeyError("Atrribute not found") 
     instance.__setattr__(k, v) 
    return instance 

で:フル方法として

return instance 

か、をそして、あなたは確かにクラスのrepr()出力を参照してくださいメソッドがインスタンスを返し、すべてが機能することを指摘してください:

>>> isinstance(form, MyForm) 
True 
>>> print(form) 
Thomas Junk 
関連する問題