Python方法,其中第一个参数是class或self

时间:2017-07-27 07:55:41

标签: python

我想编写一些Python代码,当从类型的上下文调用时,行为类似于@classmethod,但是当在对象的实例上调用时,第一个参数的行为正常,{{1}引用当前实例。即我想写:

self

2 个答案:

答案 0 :(得分:2)

我曾在daniweb中写过关于此

的代码段
from __future__ import print_function
from functools import partial

class mixedmethod(object):
    """This decorator mutates a function defined in a class into a 'mixed' class and instance method.

    Usage:

        class Spam:

            @mixedmethod
            def egg(self, cls, *args, **kwargs):
                if self is None:
                    pass # executed if egg was called as a class method (eg. Spam.egg())
                else:
                    pass # executed if egg was called as an instance method (eg. instance.egg())
    The decorated methods need 2 implicit arguments: self and cls, the former being None when
    there is no instance in the call. This follows the same rule as __get__ methods in python's
    descriptor protocol.
    """
    def __init__(self, func):
        self.func = func
    def __get__(self, instance, cls):
        return partial(self.func, instance, cls)

if __name__ == '__main__':

    class Spam(object):

        @mixedmethod
        def ham(self, cls, *args):
            if self is None:
                print("Spam.ham() was called as a class method with {0}.".format((self, cls)+ args))
            else:
                print("Spam.ham() was called as an instance method with {0}.".format((self, cls) + args))

        def __repr__(self):
            return '<Spam instance>'
    egg = Spam()
    egg.ham(5)
    Spam.ham(5)

答案 1 :(得分:1)

经过一番研究,我设法做到了这一点。我发现的第一件事是您实际上可以implement @classmethod in pure Python,如文档中所述。

有了这些知识,调整代码以测试class Foo(object): @something # <- does this exist? How can I even write it? def bar(self_or_class): print(repr(self_or_class)) Foo.bar() # Should print: <class '__main__.Foo'> inst = Foo() inst.bar() # Should print: <__main__.Foo at 0x....> 是否存在是相当简单的:

obj

我们要在文档中的示例之上做的就是检查class something(object): ''' This works like @classmethod, except the first argument is either class or self if it's available ''' def __init__(self, f): self.f = f def __get__(self, obj, klass=None): if klass is None: klass = type(obj) def newfunc(*args, **kwargs): return self.f(klass if obj is None else obj, *args, **kwargs) return newfunc obj是否None而不是obj,如果不是{。}}。