最“Pythonic” 组织类属性、构造函数参数和子类构造函数默认值的方式?
作为 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__ 中那样? 无论如何,我是否应该包含这么多带有默认值的参数?
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.
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
Yikes! Didn't expect that!
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.
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:
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?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果属性因实例而异
实例化 让它们实例化
属性,即创建它们
在
__init__
内部使用self,否则如果他们需要的话在类实例之间共享
像常数一样,把它们放在课堂上
级别。
如果你的课程确实需要通过,那么
__init__
中有很多参数,让派生类使用参数列表和
关键字参数eg
__init__
,类可以假设一些默认值,用户可以更改它们
稍后如果需要的话。
使用 4 个空格代替制表符。
如果您需要向 Dog 和关键字 arg old 添加额外的参数咬合
您可以使用 CoolDog 的各种方式
If attributes will vary from instance
to instance make them instance
attribute i.e. create them
inside
__init__
using self else if they need tobe shared between class instances
like a constant, put them at class
level.
If your class really need to pass, so
many arguments in
__init__
, letderive class use argument list and
keyword arguments e.g.
__init__
, class can assume somedefaults and user can change them
later on if needed.
Use 4 spaces instead of tab.
if you need to add an extra arg bite, to Dog and keyword arg old too
various ways you useCoolDog