2012-09-06 20 views
1

我知道那裏有一堆類似的問題。但我的問題是不同的。 我不想做出不能被覆蓋的方法。 我想保護我新創建的類不會無意中重寫某些內容。如何在Python中不小心重寫一個方法?

使用下劃線作爲前綴是相當不錯的,但很快我會得到很多帶有很多下劃線的方法。並在我的繼承類中的某個地方,我會覆蓋祖先的類方法。

我真正想要的是如此簡單的東西:

class Cat(Mammal): 
    def walk(self): 
     if ancestor_has_function('walk'): 
      parent.walk(); 
     do_something_here(); 

如果任何貓的祖先(無論它是哺乳動物,動物,或生命形式)已經「走」的方法,那麼父類的方法應該是首先執行。

是否有可能在Python中做到這一點?

編輯: 例如,這是我認爲好的答案的簡歷。希望這將有助於其他人:

class Animal(object): 
    pass 
    #def walk(self): 
    # print('animal walk') 

class Mammal(Animal): 
    def walk(self): 
     if hasattr(super(Mammal, self), 'walk') and callable(super(Mammal,self).walk): 
      super(Mammal, self).walk() 
     print('mammal walk') 

class Cat(Mammal): 
    def walk(self): 
     super(Cat, self).walk() 
     print('cat walk') 

if __name__ == '__main__': 
    cat = Cat() 
    cat.walk() 

這裏是輸出:

哺乳動物步行

貓步

嘗試以取消動物的走法,你將有它也可以工作。

+2

@Piet有它。不要有條件地重寫方法 - _always_覆蓋它們,並用'super()'調用原始方法。 – katrielalex

+0

@katrielalex「動物」類可以有或沒有「走」的方法。假設它作爲第三方庫,你不能確定它是否有某種方法,你會看到爲什麼'條件語句'是必要的。 – goFrendiAsgard

回答

7

一般來說,你可能會想,在提供至少在最通用的超類中有一個存根方法:

class Mammal(object): 
    def walk(self): 
     pass 

然後,通過調用super()在子類擴展它:

class Cat(Mammal): 
    def walk(self): 
     super(Cat, self).walk() # or just super().walk(), in Python 3+ 
     do_something_here() 

使得super()通話條件並不難,但它可能是一個壞主意:這是冗長的,脆弱的,只有鼓勵陋習。如果你真的,真的有充分的理由這樣做,你可以只使用hasattr()super對象,就像你使用任何其他對象:

class Cat(Mammal): 
    def walk(self): 
     if hasattr(super(Cat, self), 'walk'): 
      super(Cat, self).walk() 
     do_something_here() 

你只需要做到這一點在不尋常的情況下,儘管如此,例如由於某些原因,從不能依賴某些方法的第三方庫中繼承類。

+0

我以前從來不知道python有「超級」方法。它是否也適用於python 2.7? – goFrendiAsgard

+0

是的:在Python 2.2中引入了'super()'和新式類。 –

0

你可以保持你原來的方法在一個領域

class MyClass: 
    def __method(self): 
     pass 

    def __init__(self): 
     self.method = __method 

,比檢查身份和調用保存方法

1

可以使用dir()函數來獲取宣佈對某些模塊的所有名稱或類。在層次結構中更高級的類中聲明的方法也將包含在內。但是,請注意,這也將包含屬性,因此請首先檢查callable()

此外,調用父方法在Python中看起來有點不同,請參閱下面的代碼。

def walk(self): 
    if "walk" in dir(Mammal) and callable(Mammal.walk): 
     Mammal.walk(self) 
    # do something 
3

是的。 hasattr檢查是否存在具有特定名稱的屬性。 和callable檢查特定屬性是否可調用。

class Mammal(object): 
    def walk(self): 
     print "walking" 


class Cat(Mammal): 
    def walk(self): 
     if hasattr(Mammal,'walk') and callable(Mammal.walk): 
      Mammal.walk(self); 
     print "another walking!" 

現在:

>>> my_cat = Cat() 
>>> my_cat.walk() 
walking 
another walking! 

請注意,您還可以使用super讓你的父類這樣的:

if hasattr(super(Cat, self),'walk'): 
0
import inspect 

class SomeClass(): 
    def __init__(self): 
     ... 

    def somefunc(self): 
     .... 

    def someOtherFunc(self): 
     .... 


allmembers = inspect.getmembers(SomeClass, predicate=inspect.ismethod) 

getmembers返回的所有方法的列表給定的類中定義,它是一個包含方法名稱和定義元組的列表:

[('__init__', <unbound method SomeClass.__init__>), 
('somefunc', <unbound method SomeClass.somefunc>), 
('someOtherFunc', <unbound method SomeClass.someOtherFunc>)] 

由於元組的第一個元素是字符串,可以使用基於字符串的方法來過濾像__init__

allmembers = filter(lambda x: not x.startswith('__'), [x[0] for x in inspect.getmembers(SomeClass, predicate=inspect.ismethod))]) 

[('somefunc', <unbound method SomeClass.somefunc>), 
('someOtherFunc', <unbound method SomeClass.someOtherFunc>)] 

基礎的方法你可以得到的所有方法定義withi列表在類中檢查是否有類似名稱的方法,因爲getmembers會返回一個未綁定的方法實例,所以您還可以輕鬆地訪問該函數。

相關問題