Python:在非类对象上调用方法的技巧

1 投票
8 回答
1391 浏览
提问于 2025-04-15 22:26

假设你定义了一个类,这个类里面有一个方法,做了一些复杂的处理:

class A(object):
    def my_method(self):
        # Some complicated processing is done here
        return self

现在你想在另一个完全不同的类的对象上使用这个方法。比如,你想这样做:A.my_method(7)

但是你会遇到这个错误:TypeError: unbound method my_method() must be called with A instance as first argument (got int instance instead)。意思是说,你必须用类A的实例来调用这个方法,而不是直接用数字7。

那么,有没有办法让你可以在7上调用这个方法呢?我希望能避免移动这个函数或者重写它。(注意,这个方法的逻辑是依赖于self的。)

有一点要说明:我知道有些人会想说,“你这样做不对!你在滥用Python!你不应该这么做!”所以是的,我知道,我想做的事情确实很糟糕。我只是想知道有没有人知道怎么做,而不是告诉我不应该这么做。

8 个回答

2

你是做不到的。这个限制在Python 3000中已经取消了,但我猜你并没有在用那个版本。

不过,为什么你不能像这样做呢:

def method_implementation(self, x,y):
   # do whatever

class A():
   def method(self, x, y):
        return method_implementation(self, x, y)

如果你真的想挑战一下Python的极限,可以写一个描述符类来实现这个功能。大概像这样:

class Hack:
   def __init__(self, fn):
       self.fn = fn
   def __get__(self, obj, cls):
       if obj is None: # called staticly
            return self.fn
       else:
            def inner(*args, **kwargs):
                 return self.fn(obj, *args, **kwargs)
            return inner

请注意,这个代码完全没有经过测试,可能会在某些特殊情况下出问题,而且整体上来说并不太好。

2
def some_method(self):
    # Some complicated processing is done here
    return self

class A(object):
    my_method = some_method
a = A()

print some_method
print a.my_method
print A.my_method
print A.my_method.im_func
print A.__dict__['my_method']

打印:

<function some_method at 0x719f0>
<bound method A.some_method of <__main__.A object at 0x757b0>>
<unbound method A.some_method>
<function some_method at 0x719f0>
<function some_method at 0x719f0>

听起来你是在查找一个类的方法,但得到的是一个 未绑定的方法。一个 未绑定的方法 需要一个合适类型的对象作为第一个参数。

如果你想把这个函数当作普通函数来用,你需要找到它的函数版本。

6

当然,我不建议在真正的代码中这样做,但没错,你可以直接进入类里面,像用函数一样使用它的方法:

class A(object):
    def my_method(self):
        # Some complicated processing is done here
        return 'Hi'

print(A.__dict__['my_method'](7))
# Hi

撰写回答