2012-01-05 16 views
5

Cảnh báo, đây là một chút đệ quy;)chức năng Timing

Tôi đã trả lời câu hỏi này: Python:How can i get all the elements in a list before the longest element?

Và sau khi tôi nộp có nơi khác trả lời rằng nên nhanh hơn (tác giả nghĩ, và vì vậy đã làm tôi) . Tôi đã cố gắng để thời gian các giải pháp khác nhau nhưng giải pháp nên được chậm hơn đã thực sự nhanh hơn. Điều này khiến tôi nghĩ rằng có gì đó sai với mã của tôi. Hoặc là nó?

import string 
import random 
import time 

def solution1(lst): 
    return lst[:lst.index(max(lst, key=len))] 

def solution2(lst): 
    idx, maxLenStr = max(enumerate(lst), key=lambda x:len(x[1])) 
    return lst[:idx] 

# Create a 100000 elements long list that contains 
# random data and random element length 
lst = [] 
for i in range(100000): 
    s = "".join([random.choice(string.letters+string.digits) for x in range(1, random.randint(1,50))]) 
    lst.append(s) 

# Time the first solution 
start = time.time() 
solution1(lst) 
print 'Time for solution1', (time.time() - start) 

# Time the second solution 
start = time.time() 
solution2(lst) 
print 'Time for solution2', (time.time() - start) 

Cập nhật

Trước khi bất cứ ai đề cập đến lý do tại sao tôi đặt này là như một câu hỏi mới. Câu hỏi đặt ra là tôi hiểu thêm về cách đo thời gian thực hiện ...

+1

hai chức năng này không trở lại cùng một loại đối tượng – joaquin

+0

Doh! Tất nhiên cảm ơn! –

+0

Đã sửa lỗi. Nhưng điều đó thậm chí làm cho mã của tôi nhanh hơn ... Và tôi vẫn nghĩ solution2 shoud được nhanh hơn .. –

Trả lời

3

Lambda là chi phí đắt trong các giải pháp thứ hai.

Tôi profiled cả các mã và các dữ liệu hồ sơ, có vẻ, giải pháp đầu tiên là nhanh hơn

Khi wiki sẽ nói chức năng gọi là tốn kém và trong các giải pháp thứ hai, lambda và các cuộc gọi chức năng len là làm cho nó chạy chậm hơn

Xin lưu ý, tôi đã cắt xuống danh sách để chiều dài 1000 yếu tố

>>> cProfile.run('solution1(lst)') 
     5 function calls in 0.000 CPU seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.000 0.000 <pyshell#305>:1(solution1) 
     1 0.000 0.000 0.000 0.000 <string>:1(<module>) 
     1 0.000 0.000 0.000 0.000 {max} 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
     1 0.000 0.000 0.000 0.000 {method 'index' of 'list' objects} 


>>> cProfile.run('solution2(lst)') 
     2004 function calls in 0.012 CPU seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.012 0.012 <pyshell#306>:1(solution2) 
    1000 0.006 0.000 0.009 0.000 <pyshell#306>:2(<lambda>) 
     1 0.000 0.000 0.012 0.012 <string>:1(<module>) 
    1000 0.003 0.000 0.003 0.000 {len} 
     1 0.003 0.003 0.012 0.012 {max} 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
+0

Tôi muốn chấp nhận tất cả các câu trả lời vì chúng có giá trị. Nhưng tôi chỉ có thể chọn một và tôi nghĩ đây là giải thích tốt nhất. Cảm ơn :) –

2

Thời gian có vẻ ổn.

solution1 có thể nhanh hơn, bởi vì nó không sử dụng lambdas, do đó, nó không cần phải gọi mã Python trong vòng lặp. Nó lặp lại danh sách hai lần, nhưng nó không phải là một việc lớn.

+0

@joaquin Có, bạn nói đúng. Tôi đang xóa nhận xét của mình để tránh bất kỳ sự nhầm lẫn nào. Cảm ơn vì đã cho tôi biết. – jcollado

3

Có vẻ như phiên bản đầu tiên đang thực hiện nhiều cuộc gọi ít hơn cuộc gọi thứ hai.

btw, Đây có lẽ là một ví dụ về cách thành ngữ, mã đơn giản thường là cũng là một trong những nhanh hơn bằng Python

>>> dis.dis(solution1) 
    2   0 LOAD_FAST    0 (lst) 
       3 LOAD_FAST    0 (lst) 
       6 LOAD_ATTR    0 (index) 
       9 LOAD_GLOBAL    1 (max) 
      12 LOAD_FAST    0 (lst) 
      15 LOAD_CONST    1 ('key') 
      18 LOAD_GLOBAL    2 (len) 
      21 CALL_FUNCTION   257 
      24 CALL_FUNCTION   1 
      27 SLICE+2    
      28 RETURN_VALUE   
>>> dis.dis(solution2) 
    2   0 LOAD_GLOBAL    0 (max) 
       3 LOAD_GLOBAL    1 (enumerate) 
       6 LOAD_FAST    0 (lst) 
       9 CALL_FUNCTION   1 
      12 LOAD_CONST    1 ('key') 
      15 LOAD_CONST    2 (<code object <lambda> at 000000000422BEB8, file "<input>", line 2>) 
      18 MAKE_FUNCTION   0 
      21 CALL_FUNCTION   257 
      24 UNPACK_SEQUENCE   2 
      27 STORE_FAST    1 (idx) 
      30 STORE_FAST    2 (maxLenStr) 

    3   33 LOAD_FAST    0 (lst) 
      36 LOAD_FAST    1 (idx) 
      39 SLICE+2    
      40 RETURN_VALUE 
+0

Nó không quan trọng. Các hàm được gọi mất nhiều thời gian hơn, cho bất kỳ dữ liệu hợp lý lớn nào. – zch

+0

@zch xin lỗi Tôi không hiểu, bạn có thể giải thích nhận xét của mình không? – joaquin

+0

Tất cả các hướng dẫn được gọi chỉ một lần cho mỗi thử nghiệm. Thời gian chạy của hàm 'max' là tỷ lệ thuận với độ dài của danh sách đầu vào. Vì vậy, đối với danh sách đủ lớn (trong trường hợp này không thực sự lớn), chạy 'max' sẽ mất nhiều thời gian hơn so với thực hiện các hướng dẫn khác. – zch

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