我知道当我们在一个对象之外时,我们必须使用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会出现这些差异
答案 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__
来显示此信息:不会打印任何内容,因此问题不在您的代码中。