当我定义一个类时,我经常想在创建对象时为该类设置一个属性集合。到目前为止,我是通过将属性作为参数传递给 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
请您参考如下方法:
您可以使用 dataclasses project让它负责为您生成 __init__ 方法;它还将处理表示、散列和相等性测试(以及可选的丰富比较和不变性):
from dataclasses import dataclass
from typing import Optional
@dataclass
class Repository(OrderedDict, UserOwnedObject, Describable):
name: str
gitOriginURI: Optional[str] = None
gitCommitHash: Optional[str] = None
temporary: bool = False
sourceDir: Optional[str] = None
dataclasses 在 PEP 557 - Data Classes 中定义,它已被接受并包含在 Python 3.7 中。该库将在 Python 3.6 及更高版本上运行(因为它依赖于 3.6 中引入的新变量注释语法)。
该项目的灵感来自 attrs project ,它仍然提供了更多的灵 active 和选项,以及与 Python 2.7 和 Python 3.4 及更高版本的兼容性。
