2015-05-17 9 views
7

Mam klasę, która implementuje wirtualne atrybuty przy użyciu __getattr__. Atrybuty mogą być kosztowne, np. wykonanie zapytania. Teraz używam biblioteki, która sprawdza, czy mój obiekt ma atrybut, zanim faktycznie go otrzymam.Jak uniemożliwić hasattr pobieranie samej wartości atrybutu?

W konsekwencji kwerenda jest wykonywana dwa razy zamiast jednego. Oczywiście naprawdę warto wykonać __getattr__, aby naprawdę wiedzieć, czy atrybut istnieje.

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

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

Czy istnieje sposób, aby temu zapobiec?

Jeśli Python obsługuje __hasattr__, mógłbym po prostu sprawdzić, czy zapytanie istnieje, czy nie jest w stanie go uruchomić.

Mogę utworzyć pamięć podręczną, ale jest ona ciężka, ponieważ zapytanie może mieć parametry. Oczywiście serwer może samodzielnie buforować zapytania i minimalizować problem, ale nadal jest obciążony, jeśli zapytania zwracają dużą ilość danych.

Wszelkie pomysły?

+0

Jeśli dobrze rozumiem sytuację, należy buforować tylko na podstawie nazwy, aby mógł to być tylko słownik. BTW, dlaczego chcesz, aby wyglądał jak atrybut? – bereal

+0

Co chcesz zrobić, jeśli obiekt nie obsługuje zapytania? – Shashank

+0

'hasattr' nie jest lekkim testem dla atrybutu; nazywa 'getattr' zasadniczo tak jak' try: getattr ('name'); oprócz AttributeError: return False; else: return True'. – chepner

Odpowiedz

0

Myślę, że jest to generalnie zły wzór, ale zawsze można sprawdzić obiekt leżący u podstaw __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

Myślę, że OP ma do czynienia z biblioteką firm trzecich, która nazywa 'hasattr', więc wymagałoby to rozwidlenia biblioteki. – bjudson

+0

Myślę, że źle rozumiesz, klasa jest w porządku i muszę użyć __getattr __(). Plus, co powiedział @bjudson. – koriander

3

Chociaż początkowo nie lubił idei małpa łatania, że ​​jest „zły pomysł” w ogóle, natknąłem się na bardzo czystym roztworze z 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 

Zasadniczo tworzy wsparcie dla __hasattr__ w Pythonie, który jest co myślałem pierwotnie byłoby optymalnym rozwiązaniem.

+1

** Poprawianie małp jest niesamowite. ** Rubyści od dawna obejmowali brzydką małpę. Tak powinno być Pythonistas. Twoje ulepszenie '' hasattr() 'wbudowane do obsługi specjalnych metod' __hasattr __() 'jest tego doskonałym przykładem. Dzięki za odmłodzenie tego eleganckiego hackery! –

Powiązane problemy