【问题标题】:Python Class private attribute created inside an exec function in __init__ method becomes public attribute instead of private attribute [duplicate]在 __init__ 方法中的 exec 函数内创建的 Python 类私有属性变为公共属性而不是私有属性 [重复]
【发布时间】:2022-11-22 23:30:18
【问题描述】:

我正在尝试创建一个 Customer 类,它从 sqlalchemy 查询对象创建它的属性。

data = {'Name':'John Doe','Age':67}

class Customer:
   
    def __init__(self,data) -> None:
        assert type(data) == Customers
        for key in data.keys():
            exec(f"self.__{key[1:] if key.startswith('_') else key} = data['{key}']",{'self':self,'data':data})
    
    @property
    def name(self):
        return self.__Name
data['bank'] = green
person = Customer(data)

我能够将客户属性作为公共属性访问:

print(person.__Name) 它打印出John Doe

但是当我尝试通过名称方法访问属性时, 像这样 : print(person.name) 它引发了一个错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\HP\PyProject\FlaskProject\green\bank\modelx.py", line 66, in name
    return self.__Name
AttributeError: 'Customer' object has no attribute '_Customer__Name'

如何使在 exec 函数中创建的类属性充当类的私有属性而不是公共属性。

【问题讨论】:

  • 通过exec 设置时,名称修改不起作用,它是在编译时完成的,因此self.__... 必须确实存在于源代码中,而不是在运行时拼凑在一起。

标签: python python-3.x


【解决方案1】:

你在这里不需要exec。使用setattr

for key in data:
    setattr(self, key[1:] if key.startswith('_') else key, data[key])

另外,使用isinstance,而不是类型比较。

assert isinstance(data, Customers)

尽管在您的示例中,data不是Customers 的实例;这是一个普通的dict传递给Customer.__init__

【讨论】:

  • 并不是说这解决了根本问题……
  • 真的。不过,我只是建议不要首先使用 __-前缀名称。
  • 我还建议定义 __init__ 以采用显式参数,而不是接受任意的 dict,以避免在运行时出现关于实际定义了哪些属性的意外。
猜你喜欢
  • 2017-12-09
  • 2016-02-27
  • 1970-01-01
  • 2014-06-19
  • 2023-04-04
  • 1970-01-01
  • 2017-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多