2011-09-10 79 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() 
相關問題