2012-09-13 34 views
8

Trong khi cố gắng giải quyết vấn đề phức tạp hơn, tôi đã so sánh tốc độ truy cập với biến cục bộ so với biến thành viên.Tại sao truy cập biến cục bộ nhanh hơn truy cập thành viên lớp trong Python?

Dưới đây là một chương trình thử nghiệm:

#!/usr/bin/env python 

MAX=40000000 

class StressTestMember(object): 
    def __init__(self): 
     self.m = 0 

    def do_work(self): 
     self.m += 1 
     self.m *= 2 

class StressTestLocal(object): 
    def __init__(self): 
     pass 

    def do_work(self): 
     m = 0 
     m += 1 
     m *= 2 

# LOCAL access test 
for i in range(MAX): 
    StressTestLocal().do_work() 

# MEMBER access test 
for i in range(MAX): 
    StressTestMember().do_work() 

Tôi biết nó có thể trông giống như một ý tưởng tồi để nhanh chóng StressTestMemberStressTestLocal trên mỗi lần lặp nhưng nó có ý nghĩa trong chương trình mô hình hóa nơi đây là những cơ bản ghi Active Directory.

Sau một chuẩn mực đơn giản,

  • ĐỊA PHƯƠNG kiểm tra truy cập: 0m22.836
  • kiểm tra truy cập thành viên: 0m32.648s

Các phiên bản địa phương là ~ 33% nhanh hơn trong khi vẫn là một phần của một lớp học. Tại sao?

Trả lời

19

self.m += 1 có nghĩa là bạn phải tìm ra một biến địa phương gọi là self và sau đó tìm các thuộc tính được gọi là m

Tất nhiên nếu bạn chỉ cần phải tìm ra một biến địa phương, nó sẽ nhanh hơn mà không cần bước thêm.

Nó có thể hữu ích để nhìn vào những gì đang xảy ra dưới mui xe:

>>> import dis 
>>> dis.dis(StressTestLocal.do_work) 
18   0 LOAD_CONST    1 (0) 
       3 STORE_FAST    1 (m) 

19   6 LOAD_FAST    1 (m) 
       9 LOAD_CONST    2 (1) 
      12 INPLACE_ADD   
      13 STORE_FAST    1 (m) 

20   16 LOAD_FAST    1 (m) 
      19 LOAD_CONST    3 (2) 
      22 INPLACE_MULTIPLY  
      23 STORE_FAST    1 (m) 
      26 LOAD_CONST    0 (None) 
      29 RETURN_VALUE   
>>> dis.dis(StressTestMember.do_work) 
10   0 LOAD_FAST    0 (self) 
       3 DUP_TOP    
       4 LOAD_ATTR    0 (m) 
       7 LOAD_CONST    1 (1) 
      10 INPLACE_ADD   
      11 ROT_TWO    
      12 STORE_ATTR    0 (m) 

11   15 LOAD_FAST    0 (self) 
      18 DUP_TOP    
      19 LOAD_ATTR    0 (m) 
      22 LOAD_CONST    2 (2) 
      25 INPLACE_MULTIPLY  
      26 ROT_TWO    
      27 STORE_ATTR    0 (m) 
      30 LOAD_CONST    0 (None) 
      33 RETURN_VALUE   
+2

+1 Rất tốt, câu trả lời rõ ràng. – Tadeck

+0

rất đẹp. điều này xứng đáng được chấp nhận. –

+0

Vì vậy, nó làm theo nó sẽ là khôn ngoan để tạo một tham chiếu mới đến một biến lớp trong phạm vi địa phương? ví dụ: 'm = self.m'? Nó sẽ không tạo ra bất kỳ sự khác biệt nào trong bài kiểm tra này, nhưng phiên bản 'do_work()' của tôi là một vòng lặp chạy hàng triệu lần. –

5

Tên địa phương nhanh hơn vì Python thực hiện tối ưu hóa một số tên cục bộ không cần truy cập dict, mặt khác, các thuộc tính cá thể cần truy cập vào __dict__ của đối tượng.

Đây cũng là lý do tại sao tên địa phương nhanh hơn tên toàn cầu.

Các vấn đề liên quan