2012-03-20 14 views
10

Poniższy przykład pochodzi ze sterownika bazy danych REST w Pythonie 2.7.Dlaczego getattr() jest o wiele wolniejszy od siebie .__ dict __. Get()?

W metodzie __setattr__ poniżej, jeśli używam wykomentowane getattr() linię, zmniejsza wydajność instancji obiektu od 600 do 230. RPS

Dlaczego getattr() więc znacznie wolniej niż self.__dict__.get() w tym przypadku?

class Element(object): 

    def __init__(self, client): 
     self._client = client 
     self._data = {} 
     self._initialized = True 

    def __setattr__(self, key, value): 
     #_initialized = getattr(self, "_initialized", False) 
     _initialized = self.__dict__.get("_initialized", False) 
     if key in self.__dict__ or _initialized is False: 
      # set the attribute normally 
      object.__setattr__(self, key, value) 
     else: 
      # set the attribute as a data property 
      self._data[key] = value 
+1

Na marginesie, jeśli masz taką różnicę wydajności, cache 'self .__ dict__' w zmiennej lokalnej - nawet dla tylko dwóch dostępu do niego. ('dict_ = self .__ dict__' na początku' __setattr__') – jsbueno

Odpowiedz

12

W skrócie: bo getattr(foo,bar)does the same thing as foo.bar, który nie jest tym samym, co po prostu dostęp do właściwości __dict__ (na początek, getattr musi wybrać sobie prawo __dict__, ale jest o wiele więcej dzieje).

Szczegóły w tym miejscu lub powiązane: http://docs.python.org/reference/datamodel.html (szukaj słowa "getattr").

+2

@bereal: musisz ponownie przeczytać rzeczy. Niezbędne operacje dla foo .__ dict __. Get() to właściwy podzbiór getattr(). – bukzor

+2

@bereal Pamiętaj, że bajty pythonowe nie odpowiadają operacjom pierwotnym. Możesz mieć bardzo małą ilość bajtów do wywołania bardzo złożonej funkcji, podczas gdy jedno proste wyrażenie może wygenerować o wiele więcej kodu bajtowego. Ponadto, co powiedział bukzor jest poprawne i istotne. – Marcin

+0

@bereal W żaden sposób to nie zaprzecza, że ​​'foo .__ dict__' robi to samo co' getattr (foo, '__dict __') ', ponieważ możliwe jest wywoływanie' getattr (foo, '__ dict __') 'by być bardziej wydajnym niż wyłuskiwanie arbitralnego atrybutu. – Marcin

Powiązane problemy