在Python中从一个实例的成员为另一个实例创建函数
想象一下,我有 f
,它是类实例成员的函数:
class A:
def b(self):
print 'hey'
a = A()
f = a.b
如果我有同一个类的另一个实例,比方说 c = A()
如何我仅使用 f
和 c
重建一个新的 ff
,因此调用 ff()
将导致 cb() 而不是 ab()?
c = A()
ff = some_python_kungfu(f,c)
ff() #it is calling c.b()
Imagine that i have f
which is a function of a member of a class instance:
class A:
def b(self):
print 'hey'
a = A()
f = a.b
If I have another instance of the same class, let's say c = A()
how can I reconstruct a new ff
only using f
and c
, so calling ff()
would result in c.b()
instead of a.b()
?
c = A()
ff = some_python_kungfu(f,c)
ff() #it is calling c.b()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用类的方法引用而不是实例引用吗?
Can you use a method reference for the class instead of the instance reference?
因此,您想知道如何仅使用绑定方法和另一个实例将已绑定的方法重新绑定到另一个实例。可以这样完成:
__func__
属性实际上是 与 Ned Batcheldersim_func
相同,但__func__
与 python 3 向前兼容。在一种情况下这不起作用:方法内置的类。
__func__
和im_func
属性仅适用于用户定义的类。因此,这将失败:对 Ned 的解决方案进行轻微修改将对内置类和用户定义的类都有效:
那么这总是有效吗?嗯...不,但是绊脚石是一个相当晦涩且(我猜)很少出现的问题:如果方法的名称(
meth.__name__
)与它在中的名称不同类字典 ('b'
),则getattr
将返回错误的属性或引发AttributeError
。例如:这里
Ab__name__ == 'external'
而不是'b'
,因此将调用getattr(obj, 'external')
getattr(obj, 'b')
。虽然之前的两种方法都存在问题,一种使用内置类,另一种使用修补在一起的类,但这两个问题在任何情况下都不会同时发生。因此,组合适用于所有情况:
正如本页其他地方所解释的,您最好的选择可能是忽略整个混乱并以更干净的方式进行,例如使用未绑定方法并手动传入第一个参数 (
self
),如 Cixates 答案中所示。但谁知道呢,也许有一天,在某种奇怪的情况下,这可能对你们中的一些人有用。 ;)So you want to know how to rebind an already bound method to another instance, using only the bound method and the other instance. It can be done like this:
The
__func__
attribute is really the same as Ned Batcheldersim_func
, but__func__
is forward-compatible with python 3.There is one case where this will not work: methods of built-in classes. The
__func__
andim_func
attributes are only available on user-defined classes. Therefore, this will fail:A slight modification of Ned's solution will work on both built-in and user-defined classes:
So will this always work then? Well... no, but the stumbling block a rather obscure and (I guess) seldom occuring problem: if the name of the method (
meth.__name__
) is not the same as the name it has in the class dictionary ('b'
), thengetattr
will either return the wrong attribute or raise anAttributeError
. For example:Here
A.b.__name__ == 'external'
instead of'b'
, sogetattr(obj, 'external')
will be called instead ofgetattr(obj, 'b')
.While both previous approaches have problems, one with built-in classes and one with patched-together classes, both problems do not occur simultaneously in any circumstance. Therefore, a combination will work in all cases:
As explained elsewhere on this page, your best bet would probably be to ignore this whole mess and do it some cleaner way, like for instance using the unbound methods and passing in the first argument (
self
) manually, as in Cixates answer. But who knows, this may prove useful to some of you some day perhaps, in a somewhat bizarre set of circumstances. ;)我不确定这是否适用于所有情况,但是:
I'm not sure this would work in all cases, but: