2016-07-22 23 views
7

Tôi có một thuật toán mà có thể tạo ra một danh sách thủ như một máy phát điện:python không hoạt động

def _odd_iter(): 
    n=3 
    while True: 
     yield n 
     n=n+2 

def _not_divisible(n): 
    return lambda x: x % n > 0 

def primes(): 
    yield 2 
    L=_odd_iter() 
    while True: 
     n=next(L) 
     yield n 
     L=filter(_not_divisible(n), L) 

x=1 
for t in primes(): 
    print(t) 
    x=x+1 
    if x==10: 
     break 

Nhưng nếu tôi đặt chức năng lambda vào filter chức năng trực tiếp, như dưới đây:

def primes(): 
    yield 2 
    L=_odd_iter() 
    while True: 
     n=next(L) 
     yield n 
     L=filter(lambda x: x%n>0, L) 

Tôi chỉ có thể nhận danh sách lẻ, không phải danh sách chính. Có vẻ như chức năng filter không hoạt động.

Tôi có thể làm gì?

+2

Bạn đã thử thay đổi nó thành 'lambda x = x: ...'? – TigerhawkT3

+1

Điều này thật kỳ quặc. –

+0

Phiên bản đầu tiên của thuật toán không hoạt động đối với tôi chút nào. Đoạn mã sau: '_ = primes(); in tiếp theo (_); in tiếp theo (_); in tiếp theo (_); 'in' 2', rồi '3', sau đó treo. Phiên bản python nào bạn đang sử dụng? –

Trả lời

6

Đây là chương trình đơn giản minh họa cùng một vấn đề.

adders = [] 
for i in range(4): 
    adders.append(lambda a: i + a) 
print(adders[0](3)) 

Khi người dùng mong đợi đầu ra là 3, đầu ra thực tế là 6. Điều này là do một đóng trong python nhớ tên và phạm vi của một biến hơn là giá trị của nó khi lambda được tạo ra. Kể từ khi, i đã được sửa đổi bởi thời gian lambda được sử dụng, lambda sử dụng giá trị mới nhất của i.

Điều tương tự cũng xảy ra trong chức năng của bạn. Bất cứ khi nào n được sửa đổi, tất cả các hàm lambda trong các bộ lọc khác nhau cũng được sửa đổi. Vì vậy, vào thời điểm trình vòng lặp đạt đến 9, tất cả các bộ lọc là các yếu tố lọc của 7, không phải là 5 hoặc 3.

Vì, trong cách tiếp cận đầu tiên của bạn, bạn đang tạo phạm vi mới với mỗi cuộc gọi đến _not_divisible, chức năng hoạt động như dự định.

Nếu bắt buộc phải sử dụng một lambda trực tiếp, bạn có thể sử dụng một số thứ hai như thế này:

def primes(): 
    yield 2 
    L=_odd_iter() 
    while True: 
     n=next(L) 
     yield n 
     L=filter(lambda x, n=n: x%n>0, L) 
+1

Cảm ơn, @merlyn, bạn đã đưa ra một câu trả lời rất tốt –

4

Lambda làm việc là lambda x, n=n: x%n != 0. Bạn dường như cần phải làm điều này nếu bạn muốn n được chụp tại thời điểm lambda được xác định. Nếu không, một lambda chỉ tìm kiếm tên biến khi nó được xung quanh để đánh giá lambda. Trong trường hợp của bạn, tôi nghĩ rằng có nghĩa là khóa vào một giá trị n trong một lần lặp sau của vòng lặp while.

+0

Sự khác biệt trong cách đóng cửa đang làm việc trong Python 2 vs Python 3? –

+1

@ juanpa.arrivillaga Không có sự khác biệt ... tuy nhiên mã này dựa trên python 3 vì trong python 3 'filter' trả về một trình tạo chứ không phải là giá trị được tính toán. – donkopotamus

+0

@donkopotamus OH tất nhiên! Bạn nên đăng bài đó như là câu trả lời. –

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