2017-10-10 13 views
0

私は匿名クラスを作成するためのクラスがあります。プログラムで設定するにはどのようにPythonのインスタンスメソッド

class Anonyclass(object): 
    def __init__(self, **kwargs): 
     for kwarg in kwargs: 
      self.__setattr__(kwarg, kwargs[kwarg]) 

それは、彼らがアクセス権を持っていないので、しかし、私はインスタンスメソッドをこのように設定することはできません、動的にプロパティを設定するための素晴らしい作品self。例えばAnonyclass(foo = lambda x: x**2).foo(5) == 25、しかし私はそこにselfを押しているように見えることはできません...

誰かがこれを行う方法を知っていますか?

+0

[既存のオブジェクトインスタンスにメソッドを追加する](https://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance) –

答えて

2

これは、Anonyclassの新しい「クラス」インスタンスを作成していません。 インスタンス属性を設定できるように、バインドされているインスタンスを知る呼び出し可能な属性を設定できます。呼び出し可能がインスタンスに設定されているので、

from functools import partial 

class Anonyclass(object): 
    def __init__(self, **kwargs): 
     for kwarg, attr in kwargs.items(): 
      if callable(attr): 
        attr = partial(attr, self) 
      setattr(self, kwarg, attr) 

はこれが必要なmechanism Python uses to bind a method to an instance自動バイパス:

だから、最初の引数としてselfを取る引数として渡された任意の呼び出し可能と仮定すると、あなたがするようにコードを変更することができます - すべての呼び出しに対する「自己」引数を追加します。したがって、同じことを行うにはfunctools.partialを使用します。 (これはlambdaで行うことができますが、 "attr"変数が正しいメソッドにバインドされ、forループに割り当てられた最後の要素を指していないようにラムダの2つのレベルが必要です)

また、あなたが実際にバインドされた属性を持つクラスなくインスタンスを作成したい場合、あなたはちょうどあなたがあなたのコードにkwargsとして取得同じ引数を渡し、typeに電話をかけることができます

def anon_class_factory(**kwargs): 
    return type("Anonyclass", (object,), kwargs) 

これはどのようになりますkwargsで渡された関数は "実際の"メソッドとして動作します。

1

あなたは次のようにすることができます。 for kwarg, value in kwargs.items():ループを変更して、どのような種類の値が割り当てられているかを確認し、属性のデータ型および/またはプロパティ型を異なる方法で処理する必要があります。あなたの質問に例がなかったので、私は他の何ものでも試しませんでした。

class _Callable(object): 
    def __init__(self, instance, name, value): 
     self.name = name 
     self.instance = instance 
     self.__setattr__(name, value) 

    def __call__(self, *args): 
     return self.__dict__[self.name](self.instance, *args) 

class AnonyClass(object): 
    def __init__(self, **kwargs): 
     for kwarg, value in kwargs.items(): 
      setattr(self, kwarg, _Callable(self, kwarg, value)) 

value = 6.480740698407860230965967436088 
print(AnonyClass(foo=lambda self, x: x**2).foo(value)) # -> 42.0 
+0

これが機能するための可能な複製Anonyclass .__ init__の中の 'self'引数を' _Callable'インスタンスに渡す必要があります。 – jsbueno

+1

@jsbueno:真かつ固定。それを指摘してくれてありがとう。テストケースの関数/メソッドが 'self'引数にアクセスしていないので気づかなかった。 – martineau

関連する問題