2012-08-29 43 views
9

亲爱的蟒蛇专家3人,python2 VS python3函数方法结合

与python2,一个可以做到以下几点(我知道这是一个有点毛茸茸的,但在这里,这不是问题的关键:P):

class A(object): 
    def method(self, other): 
    print self, other 

class B(object): pass 

B.method = types.MethodType(A().method, None, B) 
B.method() # print both A and B instances 

与python3,没有更多的未绑定方法,只有函数。如果我想相同的行为,这听起来像我所介绍的自定义描述符,如:

class UnboundMethod: 
    """unbound method wrapper necessary for python3 where we can't turn 
    arbitrary object into a method (no more unbound method and only function 
    are turned automatically to method when accessed through an instance) 
    """ 
    def __init__(self, callable): 
     self.callable = callable 

    def __get__(self, instance, objtype): 
     if instance is None: 
      return self.callable 
     return types.MethodType(self.callable, instance) 

所以我可以做:

B.method = UnboundMethodType(A().method) 
B.method() # print both A and B instances 

是否有任何其他方式做到这一点无需编写这样的描述符?

TIA

+0

快速,脱离主题的评论:无需派生自Py3中的对象。它总是隐含的。检查,只是'print(anyobject .__ mro __)'(=方法解析顺序) – cfi

+0

我相信这是一个重复的[http://stackoverflow.com/questions/10729909/convert-builtin-function-type-to-method型合蟒-3]。然而,这个问题可能更容易找到。另外它更清晰(至少对我来说),所以我会投票保留这个... – cfi

+0

@cfi,关于对象继承的真,修正了UnboundMethod代码示例。你也是对的,这是一个类似的问题,因为绑定编译/内置函数(它没有满足答案btw) – sthenault

回答

1
B.method = lambda o: A.method(o,A()) 

b = B() 
b.method() 

b.method()然后调用A.method(b,A())。这意味着每次都会初始化一个A.为了避免这种情况:

a = A() 
B.method = lambda o: A.method(o,a) 

现在每次你打电话弘()上的一个相同的实例作为第二个参数传递B的任何实例。

0

那么,你的代码也不能在Python 2中工作,但我会得到你想要做的。你可以使用lambda,就像在Sheena的回答中,或者functools.partial。

>>> import types 
>>> from functools import partial 

>>> class A(object): 
... def method(self, other): 
...  print self, other 
... 
>>> class B(object): pass 
... 
>>> B.method = partial(A().method, A()) 
>>> B().method() 
<__main__.A object at 0x112f590> <__main__.A object at 0x1132190>