通过_setattr赋值时,Python属性设置未赋值正确的实例属性(前导下划线)__

通过_setattr赋值时,Python属性设置未赋值正确的实例属性(前导下划线)__,python,Python,在工厂方法中通过setattr设置实例属性时,我无法设置实例的正确属性 给定以下代码,其中数据是一个简单的dict,包含例如{“age”:“64”,…} def factory(data): obj = MyClass() for k, v in data.items(): setattr(obj, k, v) return obj class MyClass(object): def __init__(self): self

在工厂方法中通过
setattr
设置实例属性时,我无法设置实例的正确属性

给定以下代码,其中
数据
是一个简单的dict,包含例如
{“age”:“64”,…}

def factory(data):
    obj = MyClass()
    for k, v in data.items():
        setattr(obj, k, v)
    return obj

class MyClass(object):

    def __init__(self):

        self._age = None
        # more...


    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        some_validation(value)
        self._age = value


    def __setattr__(self, name, value):
        object.__setattr__(self, name, value)

    def __getitem__(self, item):
        return self.__dict__.get(item, None)

    def __getattr__(self, item):
        self.__dict__[item] = None
        return None

    def __str__(self):
        return json.dumps(self, default=lambda o: o.__dict__)


c = factory(data)
print(c)
打印创建的对象时,我始终获得以下输出:

{"_age": "64", ...}
但是我需要

{"age": "64", ...}

为什么
setattr
方法会指定前导下划线?

您试图实现的一些功能会混淆,例如想要打印可读的表示形式的
\uuuu dict\uuuu
,但使用私有属性作为属性。让我们从头开始,看看如何正确实现您的类

您正在尝试实现一个类,该类的属性可以作为键和属性访问。这很好,可以用更简洁的方式完成

class MyClass:
    ...

    def __getitem__(self, item):
        return self.__getattribute__(item)

    def __setitem__(self, key, value):
        return self.__setattr__(key, value)
当属性不存在时,您还希望返回
None
\uuuu getattr\uuuu
涵盖了这一点,它在属性不存在时被准确调用

    def __getattr__(self, _):
        return None
然后,您需要使用
属性
向某些属性添加一些验证。这确实是正确的做法

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        # some validation here
        self._age = value
最后,您希望能够获得实例的良好字符串表示。我们必须小心,因为我们必须添加一些我们不想打印的私有属性

我们要做的是实现一个方法
keys
,以允许强制转换到
dict
。此方法将仅返回非私有或非方法的属性的键

    def keys(self):
        return [k for k in dir(self) if not k.startswith('_') and not callable(self[k])]

    def __str__(self):
        return json.dumps(dict(self))
这是正确的做法

obj = MyClass()

obj.age = 3

print(obj)
# prints: {"age": 3}

…因为您的
age.setter
设置
\u age
您传递给工厂的数据是什么?请提供更多代码,因为有些东西不匹配,举例来说,当你打印你的对象时,它会在它的字典上打印一个dict?@OlivierMelanç,例如
{“age”:“64”,…}
@OlivierMelançon添加了
\uuu str\uuu
方法和输入数据example@kindall如果我在setter中将它设置为
self.age=value
,我会得到一个
递归错误