Python setattr vs __setattr__ UnicodeEncodeError

时间:2016-04-21 14:11:32

标签: python setattr

我知道当我们在一个对象之外时,我们必须使用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的内容:

  • setattr(obj, u"é", u"à"):引发UnicodeEncodeError
  • setattr(obj, "é", u"à"){'\xc3\xa9': u'\xe0'}
  • obj.__setattr__(u"é", u"à"){u'\xe9': u'\xe0'}

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

2 个答案:

答案 0 :(得分:0)

Python 2.7?仅限Ascii标识符。这包括2)中的代码 - ascii重音而不是.1) - unicode重音。

Unicode identifiers in Python?

3)涉及在字典中设置unicode 。法律。

请注意,__ setattr__ 几乎从不意味着您正在使用。它意味着在对象上设置属性。不拦截它并将它们填充到内部dict属性中。我也避免将属性作为名称,与get / Set意义上的属性混淆。

通常,您希望使用setattr,而不是双下划线变体。与你的开头句不同。

您通常也不会调用双下划线方法,您可以定义它们,Python的基础数据协议代表您调用它们。有点像JavaBeans获取/设置隐式调用(我认为)。

__ setattr__可能很棘手。如果你不小心,它会以意想不到的方式阻止“设置活动”。

这是一个愚蠢的例子,

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

您需要在else之后if

        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“推向”3。

答案 1 :(得分:0)

Python 2不允许使用unicode标识符:

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

据推测,在这一点上你是如此坚持,以至于你在尝试时无法解决它,因为setattr在调用__setattr__之前会经历一些处理。您可以在print的最开头插入__setattr__来显示此信息:不会打印任何内容,因此问题不在您的代码中。