2009-07-13 108 views
13

對於Python 2來說相對來說比較新,我不確定如何以最「pythonic」的方式組織我的類文件。我不會問這個問題,但是因爲Python似乎有很多方法來處理與我習慣的語言所期望的完全不同的事物。組織類屬性,構造函數參數和子類構造函數默認值的大多數「pythonic」方式?

起初,我只是治療類如何我通常把他們在C#或PHP,這當然使我絆倒了所有的地方,當我最終發現了可變值疑難雜症:

class Pants(object): 
    pockets = 2 
    pocketcontents = [] 

class CargoPants(Pants): 
    pockets = 200 

p1 = Pants() 
p1.pocketcontents.append("Magical ten dollar bill") 
p2 = CargoPants() 

print p2.pocketcontents 

哎呀!沒想到!

我花了很多時間搜索網頁,並通過一些其他項目來源尋找如何最好地安排我的類的提示,我注意到的一件事是人們似乎宣佈了很多他們的實例變量 - 可變或其他 - 在構造函數中,也堆積默認的構造函數參數相當厚。

經過這麼長時間的發展之後,我仍然對自己的不熟悉感興趣。考慮到python語言使事情看起來更加直觀和明顯的長度,在少數幾個我擁有很多屬性或者很多默認的構造函數參數的情況下,我覺得很奇怪,特別是當我「M子類:

class ClassWithLotsOfAttributes(object): 
    def __init__(self, jeebus, coolness='lots', python='isgoodfun', 
      pythonic='nebulous', duck='goose', pants=None, 
      magictenbucks=4, datawad=None, dataload=None, 
      datacatastrophe=None): 

     if pants is None: pants = [] 
     if datawad is None: datawad = [] 
     if dataload is None: dataload = [] 
     if datacatastrophe is None: datacatastrophe = [] 
     self.coolness = coolness 
     self.python = python 
     self.pythonic = pythonic 
     self.duck = duck 
     self.pants = pants 
     self.magictenbucks = magictenbucks 
     self.datawad = datawad 
     self.dataload = dataload 
     self.datacatastrophe = datacatastrophe 
     self.bigness = None 
     self.awesomeitude = None 
     self.genius = None 
     self.fatness = None 
     self.topwise = None 
     self.brillant = False 
     self.strangenessfactor = 3 
     self.noisiness = 12 
     self.whatever = None 
     self.yougettheidea = True 

class Dog(ClassWithLotsOfAttributes): 
    def __init__(self, coolness='lots', python='isgoodfun', pythonic='nebulous', duck='goose', pants=None, magictenbucks=4, datawad=None, dataload=None, datacatastrophe=None): 
     super(ClassWithLotsOfAttributes, self).__init__(coolness, python, pythonic, duck, pants, magictenbucks, datawad, dataload, datacatastrophe) 
     self.noisiness = 1000000 

    def quack(self): 
     print "woof" 

輕度愚蠢一邊(我真的不能幫助自己做飯了這些人工示例類時),假設我有一個真正的世界需要與此許多屬性一組類,我假設我的問題是:

  • 什麼是最呃,'pythonic'的方式來聲明一個具有那麼多屬性的類?如果默認值是不可變的,ala Pants.pockets,還是將它們放在構造函數ala ClassWithLotsOfAttributes.noisiness中,最好將它們放在類中?

  • 是否有一種方法可以避免重新聲明所有子類構造函數參數的缺省值,如Dog .__ init__?我應該甚至包括這麼多違反默認值的論據嗎?

+0

+1得愛你的示例屬性。另外,很好的問題。 – balpha 2009-07-13 07:05:19

回答

4
  • 如果屬性會從實例 變化,以實例讓他們實例 屬性即使用別人創建它們 內__init__如果他們需要 類實例 之間共享像一個常數,把他們放在 級別。

  • 如果你的類確實需要傳遞,所以 很多爭論在__init__,讓 派生類使用參數列表並 關鍵字參數例如

class Dog(ClassWithLotsOfAttributes): 
    def __init__(self, *args , **kwargs): 
     super(ClassWithLotsOfAttributes, self).__init__(*args , **kwargs) 
     self.coolness = "really cool!!!
  • 沒有必要通過所有變量,除了幾個重要的選項,在 __init__,類可以承擔一些 默認值,如果需要的話用戶可以以後改變他們 。
  • 使用4個空格而不是製表符。

  • ,如果你需要添加額外的ARG咬傷,到狗和關鍵字ARG老太

class CoolDog(ClassWithLotsOfAttributes): 
    def __init__(self, bite, *args , **kwargs): 
     self.old = kwargs.pop('old', False) # this way we can access base class args too 
     super(ClassWithLotsOfAttributes, self).__init__(*args , **kwargs) 
     self.bite = bite 
     self.coolness = "really really cool!!!

各種方式你useCoolDog

CoolDog(True) 
CoolDog(True, old=False) 
CoolDog(bite=True, old=True) 
CoolDog(old=True, bite=False) 
+0

會不會格式化一些格式專家,正確格式化代碼? – 2009-07-13 07:08:01

-1

這是可能的,你可以打破你的大量課程分成只能完成一項簡單任務的課程。通常類不需要這麼多屬性。

如果你確實需要擁有這麼多的屬性,我認爲你必須接受所有的屬性,特別是因爲你需要默認值。您不需要重新分配子類中的默認值(我看Anurag Uniyal顯示瞭如何)。

您應該將它們分配給self,而不是作爲類屬性。注意區別:

class Class1(object): 
    attr1 = 'abc' 

class Class2(object): 
    def __init__(self): 
     self.attr1 = 'abc' 

Class1.attr1 # returns 'abc' 
c = Class1() 
c.attr1 # Also returns 'abc' 
Class1.attr1 = 'def' 
c.attr1 # Returns 'def'! 
c.attr1 = 'abc' # Now the c instance gets its own value and will show it 
       # independently of what Class1.attr1 is. This is the same 
       # behavior that Class2 exhibits from the start.