在Python中从一个实例的成员为另一个实例创建函数

发布于 2024-12-04 08:46:37 字数 385 浏览 2 评论 0原文

想象一下,我有 f,它是类实例成员的函数:

class A:
    def b(self):
        print 'hey'

a = A()
f = a.b

如果我有同一个类的另一个实例,比方说 c = A() 如何我仅使用 fc 重建一个新的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

殤城〤 2024-12-11 08:46:37

您可以使用类的方法引用而不是实例引用吗?

class A:
    def whoami(self):
        print 'I am %s' % id(self)

a = A()
c = A()

func = A.whoami

func(a)
func(c)

Can you use a method reference for the class instead of the instance reference?

class A:
    def whoami(self):
        print 'I am %s' % id(self)

a = A()
c = A()

func = A.whoami

func(a)
func(c)
独木成林 2024-12-11 08:46:37

因此,您想知道如何仅使用绑定方法和另一个实例将已绑定的方法重新绑定到另一个实例。可以这样完成:

def some_python_kungfu(meth, obj):
    return type(meth)(meth.__func__, obj, obj.__class__)

__func__ 属性实际上是 与 Ned Batchelders im_func 相同,但 __func__ 与 python 3 向前兼容。

在一种情况下这不起作用:方法内置的类。 __func__im_func 属性仅适用于用户定义的类。因此,这将失败:

a = "that's no ordinary rabbit"
b = "consult the book of armaments"
b_split = some_python_kungfu(a.split, b)

对 Ned 的解决方案进行轻微修改对内置类和用户定义的类都有效:

def some_python_kungfu(meth, obj):
    return getattr(obj, meth.__name__)

那么这总是有效吗?嗯...不,但是绊脚石是一个相当晦涩且(我猜)很少出现的问题:如果方法的名称(meth.__name__)与它在中的名称不同类字典 ('b'),则 getattr 将返回错误的属性或引发 AttributeError。例如:

def external(self):
   pass
class A(object):
   b = external

这里 Ab__name__ == 'external' 而不是 'b',因此将调用 getattr(obj, 'external') getattr(obj, 'b')

虽然之前的两种方法都存在问题,一种使用内置类,另一种使用修补在一起的类,但这两个问题在任何情况下都不会同时发生。因此,组合适用于所有情况:

def some_python_kungfu(meth, obj):
    try:
        return type(meth)(meth.__func__, obj, obj.__class__)
    except AttributeError:
        # meth is a built-in method, so meth.__name__ is always correct
        return getattr(obj, meth.__name__)

正如本页其他地方所解释的,您最好的选择可能是忽略整个混乱并以更干净的方式进行,例如使用未绑定方法并手动传入第一个参数 (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:

def some_python_kungfu(meth, obj):
    return type(meth)(meth.__func__, obj, obj.__class__)

The __func__ attribute is really the same as Ned Batchelders im_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__ and im_func attributes are only available on user-defined classes. Therefore, this will fail:

a = "that's no ordinary rabbit"
b = "consult the book of armaments"
b_split = some_python_kungfu(a.split, b)

A slight modification of Ned's solution will work on both built-in and user-defined classes:

def some_python_kungfu(meth, obj):
    return getattr(obj, meth.__name__)

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'), then getattr will either return the wrong attribute or raise an AttributeError. For example:

def external(self):
   pass
class A(object):
   b = external

Here A.b.__name__ == 'external' instead of 'b', so getattr(obj, 'external') will be called instead of getattr(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:

def some_python_kungfu(meth, obj):
    try:
        return type(meth)(meth.__func__, obj, obj.__class__)
    except AttributeError:
        # meth is a built-in method, so meth.__name__ is always correct
        return getattr(obj, meth.__name__)

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. ;)

几度春秋 2024-12-11 08:46:37

我不确定这是否适用于所有情况,但是:

def some_python_kungfu(meth, obj):
    """Get a bound method on `obj` corresponding to the method `meth`."""
    return getattr(obj, meth.im_func.__name__)

I'm not sure this would work in all cases, but:

def some_python_kungfu(meth, obj):
    """Get a bound method on `obj` corresponding to the method `meth`."""
    return getattr(obj, meth.im_func.__name__)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文