python - 创建一个既是类方法又是实例方法的方法

标签 python decorator class-method

在 Python 中有没有一种方法可以定义一个既是类方法又是实例方法的方法,使得 clsself 都是接收者。特别是,我希望创建一个方法,(1) 在类 (Foo.method(value)) 上调用时知道调用了哪个类,并且 (2) 知道它是哪个实例在实例上调用时调用 (foo.method())。

例如,我会设想这样的事情:

class Foo:
    def __str__(self): return 'Foo()'

    @classinstancemethod
    def method(cls, self):
        print(cls, self)

class Bar(Foo):
    def __str__(self): return 'Bar()'

Foo().method()     # <class '__main__.Foo'> Foo()
Bar().method()     # <class '__main__.Bar'> Bar()
Foo.method(Foo())  # <class '__main__.Foo'> Foo()
Foo.method(Bar())  # <class '__main__.Foo'> Bar()
Bar.method(Foo())  # <class '__main__.Bar'> Foo()

请注意,我知道可以像 Foo.foo(value) 那样调用未修饰的方法,但这不是我想要的,因为它没有得到 cls 变量。如果没有 cls 变量,该方法就不知道它刚刚调用的是哪个类。它可能被称为 Bar.method(value),现在有办法知道 value 是否是 Foo 的实例.未修饰的方法更像是静态方法和实例方法,而不是类方法和实例方法。

最佳答案

这可以通过将 classinstancemethod 作为自定义实现来解决 descriptor .

简而言之,描述符必须定义一个 __get__当它作为属性访问时将被调用的方法(如 Foo.methodFoo().method)。该方法将实例和类作为参数传递并返回一个绑定(bind)方法(即它返回一个带有clsself参数的方法烘烤)。调用此绑定(bind)方法时,它将内置的 clsself 参数转发给实际方法。

class classinstancemethod:
    def __init__(self, method, instance=None, owner=None):
        self.method = method
        self.instance = instance
        self.owner = owner

    def __get__(self, instance, owner=None):
        return type(self)(self.method, instance, owner)

    def __call__(self, *args, **kwargs):
        instance = self.instance
        if instance is None:
            if not args:
                raise TypeError('missing required parameter "self"')
            instance, args = args[0], args[1:]

        cls = self.owner
        return self.method(cls, instance, *args, **kwargs)

结果:

class Foo:
    def __repr__(self): return 'Foo()'

    @classinstancemethod
    def method(cls, self):
        print((cls, self))


class Bar(Foo):
    def __repr__(self): return 'Bar()'


Foo().method()     # (<class '__main__.Foo'>, 'Foo()')
Bar().method()     # (<class '__main__.Bar'>, 'Bar()')
Foo.method(Foo())  # (<class '__main__.Foo'>, 'Foo()')
Foo.method(Bar())  # (<class '__main__.Foo'>, 'Bar()')
Bar.method(Foo())  # (<class '__main__.Bar'>, 'Foo()')

关于python - 创建一个既是类方法又是实例方法的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48808788/

相关文章:

objective-c - 无法使用 [self theMethod :] 调用类方法

typescript - 在TypeScript中每次调用静态类方法时如何调用静态方法?

IOS/objective-C : Class Method in Interface Error

python - pyglet最近有变化吗?

python - 如何像在 MATLAB 中那样将 eig 与 nobalance 选项一起使用?

python - "outsourcing"对装饰器的异常处理

类级别变量上的 Python 装饰器作为反射的元数据?

iOS: class_addMethod 添加的类方法不能被 NSInvocation 使用

python - 为什么 dict 没有在 python 多处理中更新?

Python ftplib 错误