簡體   English   中英

Python 3.4 __getattr__被調用的屬性(應該?)存在

[英]Python 3.4 __getattr__ being called for attributes that (should?) exist

我有以下類,這是為了模仿一個dict而不是實際上是一個子類:

class DB:

    def __getattribute__(self, name):
        print('__getattribute__("%s")' % name)
        if name.startswith('__') and name not in ['__init__', '__new__',
                '__dict__', '__getattribute__', '__getattr__', '__setattr__',
                '__delattr__', '__doc__', '__module__', '__del__', '__hash__']:
            return eval('self._d.%s' % name)
        print('it is not being diverted to self._d')
        raise AttributeError(name)

    def __getattr__(self, name):
        print('__getattr__("%s")' % name)
        if name.startswith('__'):
            raise AttributeError(name)
        return eval('self._d.%s' % name)

    def __setattr__(self, name, val):
        if name == '_d':
            self.__dict__[name] = val
        else:
            return self._d.__setattr__(name, val)

    def __delattr__(self, name):
        if name == '_d':
            del self.__dict__[name]
        else:
            return self._d.__delattr__(name)

    def __init__(self):
        self._d = {}

使用時會產生以下輸出:

>>> d = DB()
__getattribute__("__dict__")
it is not being diverted to self._d
__getattr__("__dict__")
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    d = DB()
  File "<pyshell#1>", line 31, in __init__
    self._d = {}
  File "<pyshell#1>", line 20, in __setattr__
    self.__dict__[name] = val
  File "<pyshell#1>", line 15, in __getattr__
    raise AttributeError(name)
AttributeError: __dict__

它不應該永遠不會到__getattr__("__dict__") ,因為self.__dict__應該已經存在,因為它是一個對象?

我已經在Python 2.6中使用了幾個月的程序中成功使用了這個對象(好吧,一個本質上完全相同的對象),我正在嘗試升級到Python 3.4。 根據我在網上可以找到的一切,Python 3應該像Python 2一樣對待它。

編輯:其他問題類似,但該問題處理__getattr__根本沒有被調用。 不過,兩者顯然都與新式和舊式的課程相關。

你正在重寫__getattribute__ - 這是屬性查找的默認實現 - 這樣在查找__dict__時會引發NameError 這會觸發對__getattr__的調用,從而引發AttributeError 結果正是您實際要求的(如果不是您所期望的)。

FWIW:

  1. 作為一般規則,不要使用eval("self.%s" % name) ,使用getattr(obj, name)
  2. 除非你真的明白你在做什么,否則不要覆蓋__getattribute__ (也不是__setattr__
  3. 如果你真的必須覆蓋它們(提示:這樣做的原因很少),委托默認實現(使用super() )。

另外:你發布的代碼在Python 2.7中“按原樣”不起作用(對self._d.__setattr__的調用引發了一個AttributeError,並使DB成為一個新式的類,與Python 3.x完全相同) 。

暫無
暫無

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

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