Python:Hack在不属于其类的对象上调用方法

时间:2010-05-06 16:00:27

标签: python class object methods

假设你定义了一个类,它有一个方法可以进行一些复杂的处理:

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)

现在,有没有可能破解内容,以便可以<{1}} 调用该方法?我想避免移动函数或重写它。 (请注意,该方法的逻辑确实取决于7。)

一个注意事项:我知道有些人会想说,“你做错了!你在滥用Python!你不应该这样做!”所以是的,我知道,这是我想做的可怕的糟糕事情。我问是否有人知道该怎么做,而不是如何向我传讲我不应该这样做。

8 个答案:

答案 0 :(得分:6)

当然我不建议在实际代码中执行此操作,但是,确定,您可以到达类内部并将其方法用作函数:

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

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

答案 1 :(得分: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 :(得分: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>

听起来你正在查找课程中的方法并获得unbound methodunbound method期望具有适当类型的对象作为第一个参数。

如果你想把这个函数作为一个函数应用,你必须得到它的函数版本的句柄。

答案 3 :(得分:0)

这就是所谓的staticmethod

class A(object):
    @staticmethod
    def my_method(a, b, c):
        return a, b, c

但是在staticmethods中,您没有获得对self的引用。

如果您想要引用class而不是instance(实例意味着引用self),您可以使用类方法:

class A(object):
    classvar = "var"

    @classmethod
    def my_method(cls, a, b, c):
        print cls.classvar
        return a, b, c

但是你只能访问类变量,而不能访问实例变量(通常在__init__构造函数中创建/定义的变量)。

如果这还不够好,那么你需要以某种方式传递“绑定”方法或将“self”传递给方法,如下所示:

class A(object):
    def my_method(self):
        # use self and manipulate the object

inst = A()
A.my_method(inst)

有些人已经说过,从另一个类继承一个类并不是一个坏主意:

class A(object):
    ... methods ...

class B(A):
    def my_method(self):
        ... use self

newA = B()

答案 4 :(得分:0)

您可以将该方法放入需要调用它的两个对象的超类中,不是吗?如果它非常关键,你不能复制它,你也不能改变它不使用自我,这是我能看到的唯一其他选择。

答案 5 :(得分:0)

>>> class A():
...     me = 'i am A'
... 
>>> class B():
...     me = 'i am B'
... 
>>> def get_name(self):
...     print self.me
... 
>>> A.name = get_name
>>> a=A()
>>> a.name()
i am A
>>> 
>>> B.name = get_name
>>> b=B()
>>> b.name()
i am B
>>> 

答案 6 :(得分:0)

为什么你不能这样做

class A(object):
    def my_method(self,arg=None):
        if (arg!=None):
           #Do Some Complicated Processing with both objects and return something 
        else:
               # Some complicated processing is done here
        return self

答案 7 :(得分:0)

在Python中函数需要包含在类中。听起来你需要的是效用函数,所以只需将其定义为:

def my_function(object):
    # Some complicated processing is done here
    return object

my_function(7)
my_function("Seven")

只要您的处理使用通过 duck typing 的魔力传递给my_function的所有对象的可用方法和属性,一切都会正常工作。