Каковы отношения между __ getattr __ и getattr?

Я знаю, что этот код является правильным:

class A:   
    def __init__(self):
        self.a = 'a'  
    def method(self):   
        print "method print"  

a = A()   
print getattr(a, 'a', 'default')   
print getattr(a, 'b', 'default')  
print getattr(a, 'method', 'default') 
getattr(a, 'method', 'default')()   

И это неправильно:

# will __getattr__ affect the getattr?

class a(object):
    def __getattr__(self,name):
        return 'xxx'

print getattr(a)

Это также неправильно:

a={'aa':'aaaa'}
print getattr(a,'aa')

Где мы должны использовать __getattr__ и getattr?

31
задан codeforester 2 May 2019 в 13:11
поделиться

3 ответа

Ответ Алекса был хорош, но предоставив вам пример кода, так как вы просили об этом : )

class foo:
    def __init__(self):
        self.a = "a"
    def __getattr__(self, attribute):
        return "You asked for %s, but I'm giving you default" % attribute


>>> bar = foo()
>>> bar.a
'a'
>>> bar.b
"You asked for b, but I'm giving you default"
>>> getattr(bar, "a")
'a'
>>> getattr(bar, "b")
"You asked for b, but I'm giving you default"

Итак, в коротком ответе

Вы используете

__getattr__ для определения того, как работать с атрибутами, которые не найдены

и

getattr для получения атрибутов

52
ответ дан 27 November 2019 в 21:28
поделиться

getattr - это встроенная функция, принимающая (как минимум) два аргумента: объект, с которого вы получаете атрибут, и строковое имя атрибута.

Если имя строки - константа, скажем 'foo', то getattr(obj, 'foo') - это точно такая же вещь , как и obj. foo.

Итак, основной случай использования встроенной функции getattr - это когда имя атрибута не является константой, а переменной. Вторым важным случаем использования является передача трёх аргументов, а не только двух: в этом случае, если атрибут отсутствует в объекте, getattr возвращает третий, "по умолчанию", аргумент, вместо того, чтобы вызывать исключение.

__getattr__ - это специальный метод, определённый в классе, который вызывается, когда запрашивается какой-то атрибут экземпляра этого класса, и другие обычные способы поставки этого атрибута (через экземпляр __dict__, слоты, свойства и т.д.) - всё это не работает. Вы можете определить его, например, когда хотите делегировать поиск других атрибутов другим объектам.

Итак, ваш второй пример неверен, потому что встроенный getattr может никогда не вызываться с одним аргументом.

Третий пример не работает, потому что словарь, из которого вы пытаетесь "получить атрибут", не имеет этого атрибута - в нем есть элементы, которые, конечно же, полностью отделены от атрибутов.

.
37
ответ дан 27 November 2019 в 21:28
поделиться

__getattr__() - специальная функция метода, которую можно определить. Когда поиск члена не удается, вызывается эта функция.

getattr() является функцией, которую можно вызвать для попытки поиска члена. Если поиск завершится успешно, Вы получите член (возможно, объект функции метода или, возможно, объект атрибута данных). getattr() также может возвращать значение по умолчанию в случае неудачи поиска.

Если Вы объявите функцию-член __getattr__(), Вы можете сделать ее успешной иногда, или Вы можете сделать ее успешной каждый раз.

class A(object):
    def __getattr__(self, name):
        return "I pretend I have an attribute called '%s'" % name

a = A()

print a.foo # prints "I pretend I have an attribute called 'foo'"

Python также имеет __getattribute__(), которая является всегда вызываемой при каждом поиске. Это очень опасно, потому что это может сделать невозможным нормальный доступ к членам.

class A(object):
    def __init__(self, value):
        self.v = value
    def __getattribute__(self, name):
        return "I pretend I have an attribute called '%s'" % name

a = A(42)

print a.v # prints "I pretend I have an attribute called 'v'"
print a.__dict__["v"] # prints "I pretend I have an attribute called '__dict__'"

Ой, теперь невозможно получить доступ к a.v!

.
17
ответ дан 27 November 2019 в 21:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: