Skip to main content
 首页 » 编程设计

python之在 Python 中创建对象时设置类属性的最佳方法是什么

2025年05月04日14qlqwjy

当我定义一个类时,我经常想在创建对象时为该类设置一个属性集合。到目前为止,我是通过将属性作为参数传递给 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 及更高版本的兼容性。