Trong khi cố gắng viết một câu trả lời cho một câu hỏi SO khác, điều gì đó thực sự kỳ lạ đã xảy ra.là lambdas python được thực hiện khác với chức năng tiêu chuẩn?
tôi về cơ bản đã đưa ra một gcd lót và nói it maybe slower because of recursion
gcd = lambda a,b : a if not b else gcd(b, a % b)
heres một thử nghiệm đơn giản:
assert gcd(10, 3) == 1 and gcd(21, 7) == 7 and gcd(100, 1000) == 100
đây là một số tiêu chuẩn:
timeit.Timer('gcd(2**2048, 2**2048+123)', setup = 'from fractions import gcd').repeat(3, 100)
# [0.0022919178009033203, 0.0016410350799560547, 0.0016489028930664062]
timeit.Timer('gcd(2**2048, 2**2048+123)', setup = 'gcd = lambda a,b : a if not b else gcd(b, a % b)').repeat(3, 100)
# [0.0020480155944824219, 0.0016460418701171875, 0.0014090538024902344]
Well thats thú vị tôi dự kiến sẽ chậm hơn nhiều nhưng thời gian là khá gần,? có thể nhập mô-đun là vấn đề ...
>>> setup = '''
... def gcd(a, b):
... """Calculate the Greatest Common Divisor of a and b.
...
... Unless b==0, the result will have the same sign as b (so that when
... b is divided by it, the result comes out positive).
... """
... while b:
... a, b = b, a%b
... return a
... '''
>>> timeit.Timer('gcd(2**2048, 2**2048+123)', setup = setup).repeat(3, 100)
[0.0015637874603271484, 0.0014810562133789062, 0.0014750957489013672]
nope vẫn còn khá gần timings ok cho phép thử các giá trị lớn hơn.
timeit.Timer('gcd(2**9048, 2**248212)', setup = 'gcd = lambda a,b : a if not b else gcd(b, a % b)').repeat(3, 100) [2.866894006729126, 2.8396279811859131, 2.8353509902954102]
[2.866894006729126, 2.8396279811859131, 2.8353509902954102]
timeit.Timer('gcd(2**9048, 2**248212)', setup = setup).repeat(3, 100)
[2.8533108234405518, 2.8411397933959961, 2.8430981636047363]
thú vị Tôi tự hỏi điều gì đang diễn ra?
Tôi luôn luôn giả định đệ quy chậm hơn vì chi phí của việc gọi một hàm, là lambdas ngoại lệ? và tại sao tôi không đạt đến giới hạn đệ quy của mình?
Nếu thực hiện sử dụng def
tôi đánh nó ngay lập tức, nếu tôi tăng độ sâu đệ quy một cái gì đó giống như 10**9
Tôi thực sự có được một segmentation fault
lẽ một chồng tràn ...
Cập nhật
>>> setup = '''
... import sys
... sys.setrecursionlimit(10**6)
...
... def gcd(a, b):
... return a if not b else gcd(b, a % b)
... '''
>>>
>>> timeit.Timer('gcd(2**9048, 2**248212)', setup = 'gcd = lambda a,b:a if not b else gcd(b, a%b)').repeat(3, 100)
[3.0647969245910645, 3.0081429481506348, 2.9654929637908936]
>>> timeit.Timer('gcd(2**9048, 2**248212)', setup = 'from fractions import gcd').repeat(3, 100)
[3.0753359794616699, 2.97499680519104, 3.0096950531005859]
>>> timeit.Timer('gcd(2**9048, 2**248212)', setup = setup).repeat(3, 100)
[3.0334799289703369, 2.9955930709838867, 2.9726388454437256]
>>>
thậm chí nhiều hơn khó hiểu ...
Tôi nghĩ rất có thể trình biên dịch Python đang tối ưu hóa biểu thức lambda của bạn thành một vòng lặp * cho bạn * (giống như cách một Lisp điển hình) triển khai sẽ tối ưu hóa các cuộc gọi đuôi đệ quy). Tuy nhiên điều này sẽ là một chi tiết thực hiện của CPython, không nhất thiết phải đúng đối với tất cả các trình thông dịch Python. – Felix
'đệ quy đuôi gọi 'yeah thats những gì Im cũng nghĩ, vẫn có thể chúng tôi luôn áp dụng nó, không có nghĩa là đệ quy là tốt hơn bằng cách sử dụng lambdas sau đó tiêu chuẩn' def' nó thực sự khó hiểu đặc biệt khi bạn xem xét nó ưu tiên khả năng đọc trên tốc độ hoặc biểu cảm 'lấy từ http://en.wikipedia.org/wiki/Portal:Python_programming –
@FelixBonkoski, Python không tối ưu hóa việc đệ quy đuôi.Mã này chỉ có một chút sử dụng ngăn xếp :) – astynax