Pythonic:在类的self.__init__函数中使用__dict__

15 投票
2 回答
9676 浏览
提问于 2025-04-17 12:38

在用 spyder 这个开发工具编写一个新类的时候,我用 pylint 来检查代码的结果,结果遇到了一些错误信息(不过代码运行得很好,没有出错)。

背景:在构造函数里,我想创建很多新的成员。通常这些成员不多,所以我用的是这样的写法:

class MyClass():
    def __init__(self):
        self.a = ...
        self.b = ...

但如果成员很多(比如说有10个),而且它们都设置为同样的初始值(比如说都是 dict()),我就想尝试这样写:

class MyClass():
    def __init__(self):
        _vars = ["a", "b", "c", ...]
        for _var in _vars:
            self.__dict__[_var] = dict()

在类的后面,我用下面的方式来引用一个成员:

class MyClass():
    def my_method(self):
        print self.c

错误来自 pylint(在 spyder 中):

当我在这个文件上使用 pylint 时,收到了一个错误信息,内容是:

MyClass.my_method: 实例 'MyClass' 没有 'c' 这个成员。

不过,代码运行得很好,没有出错,也就是说我可以毫无问题地访问成员 'c'。

问题:这样写代码合适吗?还是说我应该避免用这种方法来初始化成员?

2 个回答

6

这样做确实没问题,但一般来说,不建议直接操作 __dict__。比如说,如果你以后想为你的对象的某个属性设置一个自定义的赋值方法,那就麻烦了。

在你的例子中,你可以简单地把循环中的那一行替换成下面的代码:

setattr(self, _var, dict())
27

是的,直接更新实例字典是合理的。你也可以用 setattr 来更新变量。我见过这两种方法都在实际代码中使用过。

使用 setattr 的话,就不需要直接去修改实例字典了:

class MyClass():
    def __init__(self):
        for var in 'a', 'b', 'c':
            setattr(self, var, dict())

不过,如果你直接更新实例字典,有几个可以考虑的改进。例如,使用 vars() 而不是 __dict__ 看起来会更好一些。此外,你还可以使用 dict.update 方法来传递关键字参数:

class MyClass():
    def __init__(self):
        vars(self).update(a=dict(), b=dict(), c=dict())

撰写回答