【发布时间】:2017-12-16 16:28:22
【问题描述】:
当我定义一个类时,我经常想在创建对象时为该类设置一组属性。到目前为止,我通过将属性作为参数传递给 init 方法来做到这一点。但是,我对此类代码的重复性感到不满:
class Repository(OrderedDict,UserOwnedObject,Describable):
def __init__(self,user,name,gitOriginURI=None,gitCommitHash=None,temporary=False,sourceDir=None):
self.name = name
self.gitOriginURI = gitOriginURI
self.gitCommitHash = gitCommitHash
self.temporary = temporary
self.sourceDir = sourceDir
...
在这个例子中,我必须输入三遍name,三遍gitOriginURI,三遍gitCommitHash,三遍temporary,三遍sourceDir。只需设置这些属性。这是非常无聊的代码。
我考虑过像这样更改类以遵循以下原则:
class Foo():
def __init__(self):
self.a = None
self.b = None
self.c = None
并像这样初始化它们的对象:
f = Foo()
f.a = whatever
f.b = something_else
f.c = cheese
但从文档的角度来看,这似乎更糟,因为类的用户需要知道需要设置哪些属性,而不是简单地查看类初始化器的自动生成的 help() 字符串。
有没有更好的方法来做到这一点?
我认为可能是一个有趣的解决方案,如果有一个store_args_to_self() 方法可以将传递给init 的每个参数存储为self 的属性。有这样的方法吗?
让我对这种寻求更好方法感到悲观的一件事是,例如,查看 cPython 源代码中 date 对象的源代码时,我看到了相同的重复代码:
def __new__(cls, year, month=None, day=None):
...
self._year = year
self._month = month
self._day = day
https://github.com/python/cpython/blob/master/Lib/datetime.py#L705
而urwid,虽然被setter的使用稍微混淆了,但也有这样的“接受一个参数并将其设置为self的属性”的热土豆代码:
def __init__(self, caption=u"", edit_text=u"", multiline=False,
align=LEFT, wrap=SPACE, allow_tab=False,
edit_pos=None, layout=None, mask=None):
...
self.__super.__init__("", align, wrap, layout)
self.multiline = multiline
self.allow_tab = allow_tab
self._edit_pos = 0
self.set_caption(caption)
self.set_edit_text(edit_text)
if edit_pos is None:
edit_pos = len(edit_text)
self.set_edit_pos(edit_pos)
self.set_mask(mask)
https://github.com/urwid/urwid/blob/master/urwid/widget.py#L1158
【问题讨论】:
-
我不明白将变量名写三遍有什么问题。主要优点是它在
__init__的文档中。因此,如果您使用 IDE,它会在稍后提示名称。现在有些工作,以后会受益匪浅。此外,您不会立即分配给属性:您可能首先要验证值,然后进行一些处理,然后将属性设置为该处理的结果。
标签: python class attributes