2015-05-17 2 views
7

У меня есть класс, который реализует виртуальные атрибуты с помощью __getattr__. Атрибуты могут быть дорогими, например. выполняя запрос. Теперь я использую библиотеку, которая проверяет, есть ли у моего объекта атрибут, прежде чем он его получит.Как предотвратить hasattr от получения самого значения атрибута

Как следствие, запрос выполняется два раза вместо одного. Конечно, имеет смысл фактически выполнить __getattr__, чтобы действительно знать, существует ли атрибут.

class C(object): 
    def __getattr__(self, name): 
     print "I was accessed" 
     return 'ok' 

c = C() 
hasattr(c, 'hello') 

Есть ли способ предотвратить это?

Если Python поддерживается __hasattr__, тогда я мог бы просто проверить, существует ли запрос, он против этого.

Я могу создать кэш, но он тяжелый, так как запрос может иметь параметры. Конечно, сервер может кэшировать сами запросы и минимизировать проблему, но он по-прежнему тяжелый, если запросы возвращают большое количество данных.

Любые идеи?

+0

Если я правильно понимаю ситуацию, вам нужно кэшировать только на основе 'name', поэтому это может быть просто словарь. Кстати, почему вы хотите сделать его похожим на атрибут? – bereal

+0

Что вы хотите, если объект не поддерживает запрос? – Shashank

+0

'hasattr' не является легким тестом для атрибута; он вызывает 'getattr' по существу как' try: getattr ('name'); кроме AttributeError: return False; else: return True'. – chepner

ответ

0

Я думаю, что это, как правило, плохой шаблон, но вы всегда можете проверить базовый объект __dict__.

In [1]: class A(object): 
    ....:  @property 
    ....:  def wha(self): 
    ....:   print "was accessed" 
    ....: 

In [2]: A.__dict__ 
Out[2]: 
<dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>, 
'__doc__': None, 
'__module__': '__main__', 
'__weakref__': <attribute '__weakref__' of 'A' objects>, 
'wha': <property at 0x10f6b11b0>}> 

In [3]: a = A() 

In [4]: "wha" in a.__class__.__dict__ 
Out[4]: True 
+2

Я думаю, что OP имеет дело с сторонней библиотекой, которая вызывает 'hasattr', поэтому для этого потребуется форматирование библиотеки. – bjudson

+0

Я думаю, вы неправильно поняли, класс в порядке, и мне нужно использовать __getattr __(). Плюс, что сказал @bjudson. – koriander

3

Хотя изначально я не увлекался идеей обезьяны заплат, будучи «плохой идеей» в целом, я наткнулся на очень аккуратным решение с 1999 года !!

http://code.activestate.com/lists/python-list/14972/

def hasattr(o, a, orig_hasattr=hasattr): 
    if orig_hasattr(o, "__hasattr__"): 
     return o.__hasattr__(a) 
    return orig_hasattr(o, a) 

__builtins__.hasattr = hasattr 

По сути, это создает поддержку __hasattr__ в Python, который является то, что я думал, что первоначально будет оптимальным решением.

+1

** Обезглавливание обезьяны является удивительным. ** Рубисты давно обняли уродливую обезьяну. Так что должно быть Pythonistas. Прекрасным примером этого является расширение вашего файла 'hasattr()' builtin для поддержки '__hasattr __()' специальных методов. Спасибо за омолаживающий этот элегантный хакер! –

Смежные вопросы