2017-10-10 97 views
0

我有做一个匿名类的类:如何编程设置蟒蛇实例方法

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来完成,但是我们需要两个lambda级别,以便“attr”变量保持自己绑定到正确的方法,而不是指向在for循环中分配的最后一个元素)

另外,如果你想真正创建和不绑定的属性的情况下,你可以只需打个电话给type,传递你的kwargs您的代码相同的参数:

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

for this to work您必须将'Anonyclass .__ init__'中的'self'参数传递给'_Callable'实例。 – jsbueno

+1

@jsbueno:确实且固定。感谢您指出了这一点。没有注意到,因为testcase函数/方法没有访问它的'self'参数。 – martineau