2012-03-20 3 views
10

Ниже приведен пример драйвера базы данных REST на Python 2.7.Почему getattr() намного медленнее, чем я .__ dict __. Get()?

В __setattr__ метод ниже, если использовать закомментирована getattr() линию, это уменьшает объект производительности экземпляра от 600 до 230. RPS

Почему getattr() так много медленнее, чем self.__dict__.get() в этом случае?

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

На стороне примечания, если у вас есть такая разница в производительности, делайте кеш 'self .__ dict__' в локальной переменной - даже для двух доступа к нему. ('dict_ = self .__ dict__' в начале' __setattr__') – jsbueno

ответ

12

Короче говоря, потому что getattr(foo,bar)does the same thing as foo.bar, что не то же самое, только доступ к свойству __dict__ (для начала, getattr должен выбрать право __dict__, но есть гораздо больше происходит).

Информация, содержащаяся или связанная с здесь: http://docs.python.org/reference/datamodel.html (поиск по «getattr»).

+2

@bereal: вам нужно перечитать все. Необходимые операции для foo .__ dict __. Get() - это правильное подмножество getattr(). – bukzor

+2

@bereal Помните, что байт-коды python не соответствуют примитивным операциям. У вас может быть очень небольшое количество байт-кода для вызова очень сложной функции, в то время как одно простое выражение может генерировать намного больше байт-кода. Кроме того, то, что сказал bukzor, является правильным и актуальным. – Marcin

+0

@bereal Ни в коем случае это не доказывает, что 'foo .__ dict__' делает то же самое, что' getattr (foo, '__dict __') ', потому что можно вызвать' getattr (foo, '__ dict __') ', чтобы быть более эффективным чем разыменование произвольного атрибута. – Marcin

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