繁体   English   中英

组织类属性,构造函数参数和子类构造函数默认的大多数“pythonic”方式?

[英]Most “pythonic” way of organising class attributes, constructor arguments and subclass constructor defaults?

作为Python 2的新手,我不确定如何以最“pythonic”的方式组织我的类文件。 我不会问这个问题,但事实上Python似乎有很多方法可以做我和我以前习惯的语言非常不同的方法。

最初,我只是在处理类我通常用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语言的长度使事情看起来更直观和明显,在我有很多属性或很多默认构造函数参数的少数情况下,对我来说似乎完全奇怪,特别是当我子类化:

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__? 我是否应该在默认情况下包含这么多参数?

  • 如果属性因实例而异,则使它们成为实例属性,即如果需要在类实例(如常量)之间共享,则使用self else在__init__创建它们,将它们放在类级别。

  • 如果你的类确实需要传递__init__那么多参数,那么让派生类使用参数列表和关键字参数,例如

class Dog(ClassWithLotsOfAttributes):
    def __init__(self, *args , **kwargs):
        super(ClassWithLotsOfAttributes,    self).__init__(*args , **kwargs)
        self.coolness = "really cool!!!
  • 除了少数重要的变量之外,不需要传递所有变量,在__init__ ,class可以假设一些默认值,用户可以在以后根据需要更改它们。
  • 使用4个空格而不是制表符。

  • 如果你需要添加一个额外的arg咬,对Dog和关键字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!!!

你使用CoolDog的各种方法

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

您可以将大型课程分解为每个只执行一项简单任务的课程。 通常类不需要这么多属性。

如果你真的需要拥有那么多属性,我认为你必须同时分配它们,特别是因为你需要它们的默认值。 您不需要重新分配子类中的默认值(我看到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.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM