首页 文章

在python中使用与instance和classmethod相同的函数

提问于
浏览
6

人们可以这样做:

class master:
    @combomethod 
    def foo(param):
        param.bar() # Param could be type as well as object

class slaveClass( master ):
    @classmethod 
    def bar(cls):
        print("This is class method")

slaveType = slaveClass
slaveType.foo()

class slaveInstance( master ):
    def __init__(self, data):
        self.data = data
    def bar(self):
        print("This is "+self.data+" method")


slaveType = slaveInstance("instance")
slaveType.foo()

combomethod 在“Creating a method that is simultaneously an instance and class method”中定义 .

我的问题是,为什么这样,默认的第一个参数可以't be used as parameter of comboclass? Or at least, why can' t我将对象传递给classmethod作为第一个参数?我知道classmethod和instancemethods之间的区别,我知道装饰器,但我可能不明白如何进行内置的 @classmethodself 参数传递 . 有技术限制吗?或者,为什么 combomethod 还没有内置?

2 回答

  • 10

    combomethod 在访问时不会创建方法对象,而是一个特殊包装的函数 . 与方法类似,每个访问都会创建一个新对象,在本例中是一个新的函数对象 .

    class A:
        def __init__(self):
            self.data = 'instance'
    
        @combomethod 
        def foo(param):
            if isinstance(param, A):
                print("This is an " + param.data + " method.")
            elif param is A:
                print("This is a class method.")
    
    >>> a = A()
    >>> A.foo
    <function foo at 0x00CFE810>
    >>> a.foo
    <function foo at 0x00CFE858>
    
    >>> A.foo()
    This is a class method.
    >>> a.foo()
    This is an instance method.
    

    这是每次访问的新内容:

    >>> A.foo is A.foo
    False
    >>> a.foo is a.foo
    False
    

    foo 伪装成真的是 _wrapper

    >>> A.foo.__code__.co_name
    '_wrapper'
    

    当从类调用时,闭包有obj == None(注意'self'这里指的是combomethod,它在 self.method 中引用了原始函数对象):

    >>> print(*zip(A.foo.__code__.co_freevars, A.foo.__closure__), sep='\n')
    ('obj', <cell at 0x011983F0: NoneType object at 0x1E1DF8F4>)
    ('self', <cell at 0x01198530: combomethod object at 0x00D29630>)
    ('objtype', <cell at 0x00D29D10: type object at 0x01196858>)
    

    当作为实例的属性调用时,obj是实例:

    >>> print(*zip(a.foo.__code__.co_freevars, a.foo.__closure__), sep='\n')
    ('obj', <cell at 0x01198570: A object at 0x00D29FD0>)
    ('self', <cell at 0x01198530: combomethod object at 0x00D29630>)
    ('objtype', <cell at 0x00D29D10: type object at 0x01196858>)
    

    这是存储在combomethod中的原始函数:

    >>> A.foo.__closure__[1].cell_contents.method
    <function foo at 0x00D1CB70>
    >>> A.foo.__closure__[1].cell_contents.method.__code__.co_name
    'foo'
    

    _wrapper 执行 self.method ,将类或实例作为给定obj值的第一个参数:

    if obj is not None:
        return self.method(obj, *args, **kwargs)
    else:
        return self.method(objtype, *args, **kwargs)
    
  • 4

    用这个:

    class A(object):
    
        @classmethod
        def print(cls):
            print 'A'
    
        def __print(self):
            print 'B'
    
        def __init__(self):
            self.print = self.__print
    
    
    a = A()
    a.print()
    A.print()
    

相关问题