簡體   English   中英

Python setattr與__setattr__ UnicodeEncodeError

[英]Python setattr vs __setattr__ UnicodeEncodeError

我知道當我們在對象外部時,必須使用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會表現出這些差異

Python 2.7? 僅ASCII標識符。 其中包括2)-ascii口音的代碼,但不包括.1)-unicode口音的代碼。

Python中的Unicode標識符?

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

請注意,__ setattr__ 幾乎永遠不會像您正在使用的那樣被使用。 它旨在在對象上設置屬性。 不要截取並將它們填充到內部dict屬性中。 我也避免使用屬性作為名稱,在獲取/設置意義上與屬性混淆。

通常,您要使用setattr,而不是double下划線。 不像你的開場白。

通常,您也不會調用雙下划線方法,而是定義雙下划線方法,而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

你需要有一個elseif

        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。

Python 2不允許使用unicode標識符:

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

大概在這一點上如此堅持,以至於您無法在嘗試時解決它,因為setattr在調用__setattr__之前經過了一些處理。 您可以通過在__setattr__開始處插入print來顯示此__setattr__ :什么都不會打印,因此問題不在您的代碼中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM