在Python中创建对象时设置类属性的最佳方法是什么? [英] What is the best way to set the attributes of a class at object creation time in Python?
问题描述
当我定义一个类时,我经常想在创建对象时为该类设置属性的集合.到目前为止,我已经通过将属性作为参数传递给 init 方法来做到这一点.但是,我对此类代码的重复性感到不满意:
When I define a class, I often want to set a collection of attributes for that class upon object creation. Until now, I have done so by passing the attributes as arguments to the init method. However, I have been unhappy with the repetitive nature of such code:
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
三次.仅设置这些属性.这是非常无聊的代码.
In this example, I have to type name
three times, gitOriginURI
three times, gitCommitHash
three times, temporary
three times, and sourceDir
three times. Just to set these attributes. This is extremely boring code to write.
我已经考虑过按照以下方式更改此类:
I've considered changing classes like this to be along the lines of:
class Foo():
def __init__(self):
self.a = None
self.b = None
self.c = None
并初始化它们的对象,例如:
And initializing their objects like:
f = Foo()
f.a = whatever
f.b = something_else
f.c = cheese
但是从文档的角度来看,这似乎更糟,因为该类的用户然后需要知道需要设置哪些属性,而不是简单地为类的初始化程序查看自动生成的help()
字符串.
But from a documentation standpoint, this seems worse, because the user of the class then needs to know which attributes need to be set, rather than simply looking at the autogenerated help()
string for the class's initializer.
还有更好的方法吗?
我认为这可能是一个有趣的解决方案,那就是是否存在一个store_args_to_self()
方法,该方法可以将传递给init的每个参数都存储为self的属性.是否存在这种方法?
One thing that I think might be an interesting solution, would be if there was a store_args_to_self()
method which would store every argument passed to init as an attribute to self. Does such a method exist?
让我对此寻求更好方法感到悲观的一件事是,例如,在cPython的源代码中查看date
对象的源代码,我看到了相同的重复代码:
One thing that makes me pessimistic about this quest for a better way, is that looking at the source code for the date
object in cPython's source, for example, I see this same repetitive code:
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的属性"的热土豆代码:
And urwid, though slightly obfuscated by the use of setters, also has such "take an argument and set it as an attribute to self" hot-potato code:
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
项目,以便为您生成__init__
方法;还将进行表示,散列和相等性测试(以及可选的丰富比较和不变性):
You could use the dataclasses
project to have it take care of generating the __init__
method for you; it'll also take care of a representation, hashing and equality testing (and optionally, rich comparisons and immutability):
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-数据类 ,已被包含在Python 3.7中.该库将在Python 3.6及更高版本上运行(因为它依赖于3.6中引入的新变量注释语法).
dataclasses
were defined in PEP 557 - Data Classes, which has been accepted for inclusion in Python 3.7. The library will work on Python 3.6 and up (as it relies on the new variable annotation syntax introduced in 3.6).
该项目的灵感来自 attrs
项目,该项目仍提供了更多的灵活性和选项,以及与Python 2.7和Python 3.4及更高版本兼容.
The project was inspired by the attrs
project, which offers some more flexibility and options still, as well as compatibility with Python 2.7 and Python 3.4 and up.
这篇关于在Python中创建对象时设置类属性的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!