Python setattr 与 __setattr__ UnicodeEncodeError

Python setattr vs __setattr__ UnicodeEncodeError

我知道当我们在对象之外时,我们必须使用 setattr 方法。但是,我在使用 unicode 密钥调用 setattr 时遇到问题导致我直接使用 __setattr__

class MyObject(object):
    def __init__(self):
        self.__dict__["properties"] = dict()
    def __setattr__(self, k, v):
        self.properties[k] = v
obj = MyObject()

然后我得到 obj.properties 的以下内容:

我不明白为什么 Python 会表现出这些差异

Python2.7?仅 Ascii 标识符。这包括您在 2) 中的代码 - ascii 重音但不包括 .1) - unicode 重音。

Unicode identifiers in Python?

3) 涉及在字典中设置 unicode key。合法的。

请注意,__setattr__ 几乎从不 用于您正在做的事情。它旨在为对象设置属性。不要拦截它并将它们填充到内部 dict 属性中。我也会避免将属性作为名称,与 get/Set 意义上的属性混淆。

通常您想使用 setattr,而不是双下划线变体。不像你的开场白。

您通常也不会调用 双下划线方法,您定义它们并且Python 的底层数据协议代表您调用它们。有点像 JavaBeans get/set 隐式调用(我认为)。

__setattr__ 可能很棘手。如果您不小心,它会以意想不到的方式阻止 "setting activities"。

这是一个愚蠢的例子,

class Foo(object):

    def __setattr__(self, attrname, value):
        """ let's uppercase variables starting with k"""

        if attrname.lower().startswith("k"):
            self.__dict__[attrname.upper()] = value

foo = Foo()

foo.kilometer = 1000
foo.meter = 1

print "foo.KILOMETER:%s" % getattr(foo, "KILOMETER", "unknown")
print "foo.meter:%s" % getattr(foo, "meter", "unknown")
print "foo.METER:%s" % getattr(foo, "METER", "unknown")

输出:

foo.KILOMETER:1000
foo.meter:unknown
foo.METER:unknown

您需要在 if 之后添加一个 else

        else:
            self.__dict__[attrname] = value

输出:

foo.KILOMETER:1000
foo.meter:1
foo.METER:unknown

最后,如果您刚刚起步并且 unicode 很重要,我会评估 Python 2 vs 3 - 3 具有更好、统一的 unicode 支持。您可能需要或不需要使用 2.7 而不是 3 的原因有很多,但 unicode "pushes towards" 3.

Python 2 不允许 unicode 标识符:

>>> é = 3
  File "<stdin>", line 1
    é = 3
    ^
SyntaxError: invalid syntax

大概它在这一点上非常坚持,以至于您无法在尝试时解决它,因为 setattr 在调用 __setattr__ 之前经过了一些处理。您可以通过在 __setattr__ 的开头插入 print 来显示这一点:没有打印任何内容,因此问题不在您的代码中。