当我定义一个类时,我经常希望在创建对象时为该类设置一个属性集合。到目前为止,我是通过将属性作为参数传递给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
三次。只是为了设置这些属性。这是非常无聊的代码写。在
我曾考虑过这样的改变课程:
^{pr2}$初始化他们的对象,比如:
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
好吧,你可以这样做:
输出
^{pr2}$但是如果这样做了,那么在将
kwargs
中的键转储到实例__dict__
之前,最好检查一下它们是否正常。;)下面是一个稍微有点花哨的示例,它对传入的参数进行了一点检查。在
输出
您可以使用^{} project 让它为您生成
__init__
方法;它还将负责表示、哈希和等式测试(以及可选的丰富比较和不变性):dataclasses
是在PEP 557 - Data Classes中定义的,python3.7中已经接受了这一点。该库将在python3.6及更高版本上运行(因为它依赖于3.6中引入的新的变量注释语法)。在该项目的灵感来自于^{} project ,它提供了更多的灵活性和选项,并与python2.7和python3.4及更高版本兼容。在
对于python2.7,我的解决方案是从namedtuple继承并使用namedtuple本身作为init的唯一参数。为了避免每次使用decorator时都重载new。其优点是我们有显式的init签名w/o*args、**kwargs,因此,有很好的IDE建议
相关问题 更多 >
编程相关推荐