调用未绑定的方法,获取通过它访问的类?

时间:2016-07-28 05:16:35

标签: python-3.x

在Python3中,可以通过两种方式调用实例方法:obj.ix()Foo.ix(obj)。撇开这是否是一个好主意:当使用后者时,有没有办法获得实例方法被访问的类?

class Foo(object):
    @classmethod
    def cx(cls, obj):
        print(cls.X)
    def ix(self):
        # Any way to get the class that ix was accessed through?
        print(self.X)

class AFoo(Foo):
    X = "A"

class BFoo(Foo):
    X = "B"


a = AFoo()
AFoo.cx(a)  # Prints "A"
AFoo.ix(a)  # Prints "A"

b = BFoo()
BFoo.cx(b)  # Prints "B"
BFoo.ix(b)  # Prints "B"

AFoo.cx(b)  # Prints "A"
AFoo.ix(b)  # Prints "B" -> I would like "A", like classmethod.

BFoo.cx(a)  # Prints "B"
BFoo.ix(a)  # Prints "A" -> I would like "B", like classmethod.

正如您所看到的,使用类方法实现所需的行为是微不足道的,但似乎没有办法对实例方法执行相同的操作。

2 个答案:

答案 0 :(得分:2)

不。此信息不会保留。如果您需要该信息,则必须编写自定义描述符以实现新的方法类型。例如:

import functools

class CrazyMethod:
    def __init__(self, func):
        self.func = func
    def __get__(self, instance, owner):
        if instance is None:
            return functools.partial(self.func, owner)
        return functools.partial(self.func, instance, instance)

class Foo:
    @CrazyMethod
    def foo(accessed_through, self):
        print(accessed_through)

class Bar(Foo): pass

obj = Bar()
obj.foo()     # <__main__.Bar object at 0xb727dd4c>
Bar.foo(obj)  # <class '__main__.Bar'>
Foo.foo(obj)  # <class '__main__.Foo'>

答案 1 :(得分:1)

我已经接受了user2357112的回答,但万一有人感兴趣我找到了另一种方法(基于A class method which behaves differently when called as an instance method?):

import types

class Foo(object):
    @classmethod
    def x(cls, obj):
        print(cls.X)
    def __init__(self):
        self.x = types.MethodType(type(self).x, self)

class AFoo(Foo):
    X = "A"

class BFoo(Foo):
    X = "B"

a = AFoo()
b = BFoo()

a.x()       # Prints "A"
AFoo.x(a)   # Prints "A"
AFoo.x(b)   # Prints "A"

b.x()       # Prints "B"
BFoo.x(b)   # Prints "B"
BFoo.x(a)   # Prints "B"