2009-07-13 104 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.