3 ответов:
переопределение
__getattr__должно быть прекрасно --__getattr__вызывается только в крайнем случае, т. е. если в экземпляре нет атрибутов, соответствующих имени. Например, если вы получаете доступfoo.bar, потом__getattr__будет вызываться только еслиfooне имеет атрибута под названиемbar. Если атрибут является тем, который вы не хотите обрабатывать, поднимитеAttributeError:class Foo(object): def __getattr__(self, name): if some_predicate(name): # ... else: # Default behaviour raise AttributeErrorоднако, в отличие от
__getattr__,__getattribute__будет вызван первым (работает только для новых классов стилей, т. е. тех, которые наследуют от объект.) В этом случае вы можете сохранить поведение по умолчанию следующим образом:class Foo(object): def __getattribute__(self, name): if some_predicate(name): # ... else: # Default behaviour return object.__getattribute__(self, name)посмотреть документы Python для более.
class A(object): def __init__(self): self.a = 42 def __getattr__(self, attr): if attr in ["b", "c"]: return 42 raise AttributeError("%r object has no attribute %r" % (self.__class__, attr)) # exception text copied from Python2.6
>>> a = A() >>> a.a 42 >>> a.b 42 >>> a.missing Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 8, in __getattr__ AttributeError: 'A' object has no attribute 'missing' >>> hasattr(a, "b") True >>> hasattr(a, "missing") False
чтобы расширить ответ Майкла, если вы хотите сохранить поведение по умолчанию с помощью
__getattr__, вы можете сделать это вот так:class Foo(object): def __getattr__(self, name): if name == 'something': return 42 # Default behaviour return self.__getattribute__(name)Теперь сообщение об исключении является более описательным:
>>> foo.something 42 >>> foo.error Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __getattr__ AttributeError: 'Foo' object has no attribute 'error'
Comments