【问题标题】:How to add attributes to a class in __init__() of the class with __dict__ in Python 3?如何在 Python 3 中使用 __dict__ 为类的 __init__() 中的类添加属性?
【发布时间】:2019-04-09 05:07:42
【问题描述】:

以下代码可在 Python 2.7 中使用 _x.__dict__['c']=8

class _x:
    def __init__(self):
        self.a = 6
        self.b = 7
        _x.__dict__['c']=8
        print("good!")

y=_x()
print(y.__dict__)
print(_x.__dict__)

输出:

good!
{'a': 6, 'b': 7}
{'c': 8, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x00000000049227B8>}

以上代码不适用于 Python 3.6 _x.__dict__['c']=8 出现错误:

TypeError                             Traceback (most recent call last)
<ipython-input-5-b4146e87f5a4> in <module>()
      6         print("good!")
      7 
----> 8 y=_x()
      9 print(y.__dict__)
     10 print(_x.__dict__)

<ipython-input-5-b4146e87f5a4> in __init__(self)
      3         self.a = 6
      4         self.b = 7
----> 5         _x.__dict__['c']=8
      6         print("good!")
      7 

TypeError: 'mappingproxy' object does not support item assignment

有什么建议吗?

【问题讨论】:

  • 为什么要通过__dict__?你只是不知道setattr吗?
  • 你为什么要这样做?对于新构造而言,仅在类上设置值通常是一个非常糟糕的主意(在少数情况下有意义的情况是当您对实例进行编号等时,但在这种情况下,应使用基值定义类变量在定义时)。这闻起来like an XY problem
  • 找到了解决方案:_x.c = 8 有效。
  • user2357112,ShadowRanger:我正在将一个 python 应用程序(由另一位作者)从 2 转换为 3。只想让它现在工作,然后弄清楚“为什么”。感谢您的 cmets。

标签: python


【解决方案1】:

您是否有任何理由尝试使用非公共接口?如果由于某种原因您想在实例化期间设置类属性,请尝试

class A:
    def __init__(self):
        self.__class__.k = 1

如果要动态设置访问权限,请使用setattr

this answer 中描述的可变性更改背后的原因

【讨论】:

  • 注意:如果 A 是子类,这将在行为上有所不同; OP 的方法将始终在A 上设置属性,而如果适用,这将在子类上设置属性。普通的A.k = 1(或作为仅在 Python 3+ 上有效的偷偷摸摸的方法,并且取决于 CPython 实现细节,__class__.k = 1)将匹配 OP 的设计。
  • 正确,直接设置也是一种选择,但在适当的界面中更不可行,IMO。
  • 非常感谢您的帮助,Slam。
【解决方案2】:

您可以通过在变量名之前指定类名来设置类变量。

变化:

_x.__dict__['c']=8

到:

_x.c=8

【讨论】:

  • blhsing,谢谢。
  • 很高兴能提供帮助。如果您认为此答案正确,您能否将其标记为已接受? (点击答案旁边的灰色复选标记。)
猜你喜欢
  • 1970-01-01
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多