2011-09-10 90 views
6

我们可以做这样的事情:使用相同的功能,实例和类方法在Python

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”定义。

我的问题是,为什么它是这样的,默认的第一个参数不能用作comboclass的参数。或者至少,为什么我不能将对象传递给classmethod作为第一个参数。我知道什么是classmethod和instancemethods和装饰器是什么区别,但我可能不明白,如何内置@classmethodself参数传递。是否只有一些技术限制?或者为什么不是combomethod已经内置?

+2

请不要在SO帖子中使用文本说话(“smth”)。 –

+0

我不能让你在这里问的头或尾... –

+0

@Ignacio我想知道如果我做这一切都错了,是否有更简单的方法?我认为可能有某种方式可以做同样的事情,如果没有,为什么不呢? – Johu

回答

3

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 ==无叫(请注意,'自我“在这里是指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) 
+0

所以你告诉我combomethod是如何工作的,而且我对它的了解最多。感谢你的付出!你能不能告诉我,为什么它不好,可以以更好的方式完成?函数周围的包装会使内存效率低下? – Johu

9

使用这个:

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()