2012-03-20 13 views
10

L'esempio seguente proviene da un driver di database REST su Python 2.7.Perché getattr() è molto più lento di self .__ dict __. Get()?

Nel metodo __setattr__ seguito, se uso il commentata getattr() linea, riduce le prestazioni istanza dell'oggetto da 600 a 230. RPS

Perché getattr() molto più lento rispetto self.__dict__.get() in questo caso?

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

Nota a margine, se si riscontra una tale differenza di prestazioni, memorizzare nella cache 'self .__ dict__' in una variabile locale, anche solo per due accessi. ('dict_ = self .__ dict__' all'inizio di' __setattr__') – jsbueno

risposta

12

In breve: perché getattr(foo,bar)does the same thing as foo.bar, che non è la stessa cosa come solo l'accesso alla proprietà __dict__ (tanto per cominciare, getattr deve selezionare il diritto __dict__, ma c'è molto di più in corso).

Dettagli contenuti in, o collegati a qui: http://docs.python.org/reference/datamodel.html (cercare "getattr").

+2

@bereal: è necessario rileggere le cose. Le operazioni necessarie per foo .__ dict __. Get() sono un sottoinsieme appropriato di getattr(). – bukzor

+2

@bereal Ricordare che i bytecode python non corrispondono alle operazioni primitive. Puoi avere una quantità molto piccola di bytecode per chiamare una funzione molto complessa, mentre una semplice espressione può generare molto più bytecode. Inoltre, ciò che ha detto il bukzor è corretto e pertinente. – Marcin

+0

@bereal In nessun modo questo sminuisce che 'foo .__ dict__' fa lo stesso di' getattr (foo, '__dict __') ', perché è possibile chiamare' getattr (foo, '__ dict __') 'per essere più efficiente di dereferenziare un attributo arbitrario. – Marcin

Problemi correlati