Ошибка доступа к атрибуту Python - PullRequest
2 голосов
/ 24 марта 2011

Я пытаюсь настроить доступ к атрибутам в классе (python2.7). Скажем, я определил следующий класс:

class testAttrAccess(object):
    def __init__(self):
        self.data = {"attr1":"value1","attr2":"value2"}

    def __getattr__(self,name):
        try:
            return self.data[name]
        except KeyError:
            pass

        raise AttributeError

Тогда я получаю:

In [85]: a = testAttrAccess()

In [86]: a.attr2
Out[86]: 'value2'

In [87]: a.__getattr__('attr2')
Out[87]: 'value2'

In [88]: a.__getattribute__('attr2')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/Users/laserson/temp/<ipython console> in <module>()

AttributeError: 'testAttrAccess' object has no attribute 'attr2'

Однако, в соответствии с документацией Python

Если класс также определяет __getattr__(), последний не будет вызываться, если __getattribute__() не вызовет его явно или не вызовет AttributeError.

Так что, если __getattribute__() вызывает AttributeError, то почему бы __getattr__() не вызывать и не возвращать правильное значение?

Ответы [ 4 ]

1 голос
/ 24 марта 2011
So if __getattribute__() is raising an AttributeError, then why isn't __getattr__() being called and returning the proper value?

Это применимо, только если python вызывает для вас __getattribute__ как часть обычного доступа к атрибутам, а не если вы сами вызываете __getattribute__.По сути, вы почти никогда не должны вызывать метод python вида __foo__ Такие методы используются для реализации поведения, зависящего от других операций.

1 голос
/ 24 марта 2011

__getattribute__() по-прежнему по умолчанию, поэтому он достигает self.attr2 вместо self.data['attr2']

0 голосов
/ 25 марта 2011

Вдохновленный @lazyr, это решение, похоже, тоже работает. Мне кажется, проще ... поднимает ли кто-нибудь красные флаги?

class testAttrAccess(object):
    def __init__(self):
        self.data = {"attr1":"value1","attr2":"value2"}

    def __getattribute__(self,name):
        try:
            return object.__getattribute__(self,name)
        except AttributeError:
            pass

        try:
            return self.data[name]
        except KeyError:
            pass

        raise AttributeError

Следующая сессия дает:

In [108]: a = testAttrAccess()

In [109]: a.attr2
Out[109]: 'value2'

In [110]: a.__getattribute__('attr2')
Out[110]: 'value2'

In [111]: a.__getattr__('attr2')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/Users/laserson/temp/<ipython console> in <module>()

/Users/laserson/temp/<ipython console> in __getattribute__(self, name)

AttributeError: 

In [112]: a.qwerty
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/Users/laserson/temp/<ipython console> in <module>()

/Users/laserson/temp/<ipython console> in __getattribute__(self, name)

AttributeError: 
0 голосов
/ 24 марта 2011

a.__getattr__ вызывается, только если атрибут не найден в a.__dict__.

a.__getattribute__ вызывается во всех случаях, если оно определено.

Как вы знаете, a.__getattribute__(attr) является синтаксическим сахаром для type(a).__getattribute__(a, attr), но, поскольку этот метод не определен в testAttrAccess, вызывается родительский метод object.__getattribute__(a, attr). Исходя из ваших результатов, мы можем сделать вывод, что не object.__getattribute__ вызывает __getattr__. Вероятно, об этом позаботится переводчик.

Вы можете заставить свою программу работать, изменив ее следующим образом:

class testAttrAccess(object):
    def __init__(self):
        self.data = {"attr1": "value1", "attr2": "value2"}

    def __getattribute__(self, name):
        try:
            return object.__getattribute__(self, name)
        except AttributeError:
            if name == "__getattr__":
                return object.__getattribute__(self, "__getattribute__")
        try:
            return object.__getattribute__(self, "data")[name]
        except KeyError:
            raise AttributeError
a = testAttrAccess()

print a.attr2
print a.__getattr__('attr2')
print a.__getattribute__('attr2')
print a.qwerty

Выход:

value2
value2
value2
Traceback (most recent call last):
  File "test.py", line 20, in 
    print a.qwerty
  File "test.py", line 13, in __getattribute__
    raise AttributeError
AttributeError
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...