2017-09-23 21 views
5

Tôi hiểu các biểu thức lambda bình thường, chẳng hạn nhưConfused về biểu thức lambda trong python

g = lambda x: x**2 

Tuy nhiên, đối với một số người phức tạp, tôi là một chút nhầm lẫn về họ. Ví dụ:

for split in ['train', 'test']: 
    sets = (lambda split=split: newspaper(split, newspaper_devkit_path)) 

def get_imdb(): 
    return sets() 

Trường hợp newspaper là một hàm. Tôi đã tự hỏi những gì thực sự là sets là và tại sao chức năng get_imdb có thể trả lại giá trị sets()

Cảm ơn sự giúp đỡ của bạn!

Added: Các mã đang thực sự từ đây factory.py

+3

Bạn có chắc chắn mã đó là chính xác không? Nó thực sự kỳ quặc để giữ lại 'bộ' mỗi lần lặp lại. –

+0

Tôi nghĩ đây chỉ là nỗ lực của OP trong việc tạo ra một ví dụ tối thiểu. Mã này không phải là của riêng mình theo câu hỏi riêng của mình. –

Trả lời

2

sets đang được chỉ định một lambda không thực sự phải chấp nhận các yếu tố đầu vào, mà bạn thấy từ cách nó được gọi. Lambdas nói chung hoạt động như các hàm bình thường, và do đó có thể được gán cho các biến như g hoặc sets. Định nghĩa của sets được bao quanh bởi một bộ ngoặc đơn bổ sung không có lý do rõ ràng. Bạn có thể bỏ qua những parens bên ngoài.

Lambdas có thể có tất cả các loại đối số vị trí, từ khóa và đối số mặc định giống nhau mà chức năng bình thường có thể. Số lambda sets có thông số mặc định có tên là split. Đây là thành ngữ phổ biến để đảm bảo rằng sets trong mỗi lần lặp của vòng lặp nhận giá trị của split tương ứng với lần lặp đó thay vì chỉ là một từ lần lặp cuối cùng trong tất cả các trường hợp.

Không có tham số mặc định, split sẽ được đánh giá trong lambda dựa trên không gian tên tại thời điểm được gọi. Khi vòng lặp hoàn thành, split trong không gian tên của hàm bên ngoài sẽ chỉ là giá trị cuối cùng của vòng lặp đó.

Thông số mặc định được đánh giá ngay lập tức khi đối tượng hàm được tạo. Điều này có nghĩa là giá trị của tham số mặc định split sẽ ở bất kỳ nơi nào trong vòng lặp của vòng lặp tạo ra nó.

Ví dụ của bạn hơi gây hiểu lầm vì nó loại bỏ tất cả các giá trị thực tế của sets ngoài giá trị cuối cùng, làm cho tham số mặc định thành lambda vô nghĩa. Dưới đây là một ví dụ minh họa những gì sẽ xảy ra nếu bạn giữ tất cả các lambdas. Đầu tiên với thông số mặc định:

 
sets = [] 
for split in ['train', 'test']: 
    sets.append(lambda split=split: split) 
print([fn() for fn in sets]) 

Tôi đã cắt ngắn lambdas để chỉ trả về thông số đầu vào của chúng nhằm mục đích minh họa. Ví dụ này sẽ in ['train', 'test'], như mong đợi.

Nếu bạn làm điều tương tự mà không có tham số mặc định, sản lượng sẽ được ['test', 'test'] thay vì:

 
sets = [] 
for split in ['train', 'test']: 
    sets.append(lambda: split) 
print([fn() for fn in sets]) 

Điều này là do 'test' là giá trị của split khi tất cả các lambdas được đánh giá.

+0

Khi chúng ta gọi 'fn', có thể không có tham số? Lấy ví dụ về 'g = lambda x: x ** 2', chúng ta cần gọi nó là' g (2) ', và' g() 'không có ý nghĩa. Nếu nó có các tham số mặc định thì có vẻ như không sao vì các giá trị đã được tạo khi tạo nó.Nhưng đối với những cái không có tham số mặc định, chúng ta có nên sử dụng 'print ([fn (split) cho fn trong tập hợp))' cho ví dụ cuối cùng không? –

+1

Trong ví dụ cuối, hàm lambda được định nghĩa là 'lambda: split', i. e. nó là một cái gì đó như 'def func():' (một hàm không có tham số). Nếu hàm lambda sử dụng tham số (s), nó phải được định nghĩa e. g. như 'lambda x: x ** 2' (ví dụ đầu tiên, dễ hiểu của bạn) - với tên tham số giữa' lambda' và ':'. – MarianD

0

Một chức năng lambda:

func = lambda x: x**2 

thể được viết lại gần như tương đương:

def func(x): 
    return x**2 

Sử dụng một trong hai cách, bạn có thể gọi theo cách này:

func(4) 

Trong ví dụ của bạn,

sets = lambda split=split: newspaper(split, newspaper_devkit_path) 

thể được viết lại:

def sets(split=split): 
    return newspaper(split, newspaper_devkit_path) 

và do đó có thể được gọi là:

sets() 

Khi bạn viết như sau:

def get_imdb(): 
    return sets() 

bạn đang xác định "đóng cửa". Một tham chiếu đến hàm sets được lưu trong phạm vi get_imdb để nó có thể được gọi sau này ở bất cứ nơi nào get_imdb được gọi.

+0

Bạn không giải quyết mục đích của tham số mặc định hoặc thực tế là tất cả các giá trị của 'bộ' nhưng giá trị cuối cùng bị loại bỏ. 'def get_imb(): ...' không * không * tạo ra một đóng. Nó chỉ làm cho một cuộc gọi chức năng bình thường. –

0

Có thể bạn đang bối rối về phần split=split. Điều này có ý nghĩa tương tự như nó sẽ có trong một chức năng thông thường: sự chia rẽ bên trái là một tham số của hàm lambda và sự chia tách bên phải là giá trị mặc định phân chia bên trái sẽ mất khi không có giá trị nào được cung cấp. Trong trường hợp này, giá trị mặc định sẽ là biến số split được xác định trong vòng lặp for.

Vì vậy, trả lời câu hỏi đầu tiên của bạn (là những gì sets?):

sets là một biến mà một chức năng ẩn danh (hoặc chức năng lambda) được gán. Điều này cho phép hàm lambda được tham chiếu và được sử dụng thông qua biến số sets.

Câu hỏi thứ hai của bạn (tại sao có thể trả lại sets()?), Tôi trả lời:

sets là một biến hoạt động như một hàm, thêm dấu ngoặc đơn sau khi nó gọi hàm lambda. Vì không có tham số nào, tham số split lấy giá trị 'test', là giá trị cuối cùng cho biến vòng lặp split mất. Điều đáng lưu ý ở đây là, vì sets không được định nghĩa bên trong hàm get_imdb, trình thông dịch sẽ tìm định nghĩa sets nằm ngoài phạm vi get_imdb (và tìm một tham chiếu đến hàm lambda).