最“pythonic"组织类属性、构造函数参数和子类构造函数默认值的方法? [英] Most "pythonic" way of organising class attributes, constructor arguments and subclass constructor defaults?

查看:76
本文介绍了最“pythonic"组织类属性、构造函数参数和子类构造函数默认值的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为 Python 2 的新手,我不确定如何最好地以最pythonic"的方式组织我的类文件.我不会问这个,但事实上 Python 似乎有很多做事的方法与我对我习惯的语言的期望大不相同.

Being relatively new to Python 2, I'm uncertain how best to organise my class files in the most 'pythonic' way. I wouldn't be asking this but for the fact that Python seems to have quite a few ways of doing things that are very different to what I have come to expect from the languages I am used to.

最初,我只是按照我通常在 C# 或 PHP 中处理它们的方式来处理类,当我最终发现可变值的问题时,这当然让我到处乱跑:

Initially, I was just treating classes how I'd usually treat them in C# or PHP, which of course made me trip up all over the place when I eventually discovered the mutable values gotcha:

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

哎呀!没想到!

我花了很多时间在网络上搜索并通过其他项目的一些来源寻找有关如何最好地安排我的课程的提示,我注意到的一件事是人们似乎声明了很多他们的实例变量- 可变或其他 - 在构造函数中,并且还将默认构造函数参数堆得很厚.

I've spent a lot of time searching the web and through some source for other projects for hints on how best to arrange my classes, and one of the things I noticed was that people seem to declare a lot of their instance variables - mutable or otherwise - in the constructor, and also pile the default constructor arguments on quite thickly.

像这样发展了一段时间后,我仍然对它的不熟悉感到有些头疼.考虑到 python 语言使事情看起来更直观和明显的长度,在我有很多属性或很多默认构造函数参数的少数情况下,这对我来说似乎完全奇怪,尤其是当我'm 子类化:

After developing like this for a while, I'm still left scratching my head a bit about the unfamiliarity of it. Considering the lengths to which the python language goes to to make things seem more intuitive and obvious, it seems outright odd to me in the few cases where I've got quite a lot of attributes or a lot of default constructor arguments, especially when I'm subclassing:

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"

抛开轻微的愚蠢(我在编写这些人工示例类时真的无能为力),假设我在现实世界中需要一组具有这么多属性的类,我想我的问题是:

Mild silliness aside (I can't really help myself when cooking up these artificial example classes), assuming I have a real-world need for a set of classes with this many attributes, I suppose my questions are:

  • 声明具有这么多属性的类的最,呃,pythonic"方式是什么?如果默认值是不可变的,最好将它们放在类上,ala Pants.pockets,还是将它们放在构造函数中更好,ala ClassWithLotsOfAttributes.noisiness?

  • What is the most, uhh, 'pythonic' way of declaring a class with that many attributes? Is it best to put them against the class if the default is immutable, ala Pants.pockets, or is it better to put them in the constructor, ala ClassWithLotsOfAttributes.noisiness?

有没有办法消除重新声明所有子类构造函数参数的默认值的需要,就像在 Dog.__init__ 中一样?无论如何,我是否应该在默认值中包含这么多参数?

Is there a way to eliminate the need to redeclare the defaults for all of the subclass constructor arguments, as in Dog.__init__? Should I even be including this many arguments with defaults anyway?

推荐答案

  • 如果属性会因实例而异实例使它们实例化属性,即创建它们inside__init__ 使用 self else 如果他们需要在类实例之间共享就像一个常数,把它们放在课堂上水平.

    • If attributes will vary from instance to instance make them instance attribute i.e. create them inside__init__ using self else if they need to be shared between class instances like a constant, put them at class level.

      如果你的课真的需要通过,那么__init__ 中有很多参数,让派生类使用参数列表和关键字参数,例如

      If your class really need to pass, so many arguments in __init__, let derive class use argument list and keyword arguments e.g.

      class Dog(ClassWithLotsOfAttributes):
          def __init__(self, *args , **kwargs):
              super(ClassWithLotsOfAttributes,    self).__init__(*args , **kwargs)
              self.coolness = "really cool!!!

      • 除了几个重要的变量外,不需要传递所有变量,在__init__,类可以假设一些默认值和用户可以更改它们以后需要的话.
      • 使用 4 个空格代替制表符.

        • No need of passing all variables except few important ones, in __init__, class can assume some defaults and user can change them later on if needed.
        • Use 4 spaces instead of tab.

          如果您需要添加额外的 arg 指令,也可以添加到 Dog 和关键字 arg old

          if you need to add an extra arg bite, to Dog and keyword arg old too

          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的各种方式

          various ways you useCoolDog

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

          这篇关于最“pythonic"组织类属性、构造函数参数和子类构造函数默认值的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆