2012-03-20 16 views
10

Ví dụ bên dưới là từ trình điều khiển cơ sở dữ liệu REST trên Python 2.7.Tại sao getattr() chậm hơn nhiều so với bản thân .__ dict __. Get()?

Trong __setattr__ phương pháp dưới đây, nếu tôi sử dụng các nhận xét ra getattr() dòng, nó làm giảm các đối tượng instantiation hiệu suất từ ​​600 rps để 230.

Tại sao getattr() nên chậm hơn nhiều so với self.__dict__.get() trong trường hợp này?

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

Trên một lưu ý phụ, nếu bạn đang có sự khác biệt về hiệu suất, hãy lưu vào bộ nhớ cache 'self .__ dict__' trong biến cục bộ - ngay cả khi chỉ có hai quyền truy cập vào nó. ('dict_ = self .__ dict__' khi bắt đầu' __setattr__') – jsbueno

Trả lời

12

Nói tóm lại: vì getattr(foo,bar)does the same thing as foo.bar, mà không phải là điều tương tự như chỉ truy cập vào __dict__ tài sản (cho một sự khởi đầu, getattr phải chọn đúng __dict__, nhưng có nhiều thứ khác xảy ra).

Chi tiết có trong hoặc được liên kết tới đây: http://docs.python.org/reference/datamodel.html (tìm kiếm "getattr").

+2

@bereal: bạn cần phải đọc lại mọi thứ. Các hoạt động cần thiết cho foo .__ dict __. Get() là một tập hợp con thích hợp của getattr(). – bukzor

+2

@bereal Hãy nhớ rằng các mã bytecode python không tương ứng với các hoạt động nguyên thủy. Bạn có thể có một số lượng rất nhỏ bytecode để gọi một hàm rất phức tạp, trong khi một biểu thức đơn giản có thể tạo ra nhiều bytecode hơn. Ngoài ra, những gì bukzor nói là chính xác và có liên quan. – Marcin

+0

@bereal Không có cách nào điều này bác bỏ rằng 'foo .__ dict__' không giống như' getattr (foo, '__dict __') ', bởi vì có thể gọi' getattr (foo, '__ dict __') 'để hiệu quả hơn hơn dereferencing một thuộc tính tùy ý. – Marcin