2011-05-25 23 views
11

Khi tôi thực thi mã này trong python 2,6Strange giảm hành vi

reduce(lambda x,y: x+[y], [1,2,3],[]) 

tôi nhận được [1, 2, 3] như mong đợi. Nhưng khi tôi thực hiện điều này một (Tôi nghĩ rằng đó là tương đương với trước)

reduce(lambda x,y: x.append(y), [1,2,3],[]) 

tôi nhận được một thông báo lỗi

Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in <lambda> 
AttributeError: 'NoneType' object has no attribute 'append' 

Tại sao hai dòng mã không cho kết quả tương tự?

Trả lời

14

x.append(y) không tương đương với x+[y]; append sửa đổi một danh sách tại chỗ và không trả về gì, trong khi x+[y] là một biểu thức trả về kết quả.

+0

Cảm ơn bạn. Bây giờ tôi thấy rằng tôi nên đọc tài liệu một cách chu đáo hơn. –

6

Đối số chức năng cho reduce được mong đợi là trả lại kết quả của thao tác.

x+[y] thực hiện điều đó, trong khi x.append(y) thì không (sau này sửa đổi x và trả về None).

7

reduce gọi hàm và sử dụng giá trị trả về làm kết quả mới. append trả về None và do đó yêu cầu append tiếp theo thất bại. Bạn có thể viết

def tmpf(x,y): 
    x.append(y) 
    return x 
reduce(tmpf, [1,2,3], []) 

và nhận kết quả chính xác. Tuy nhiên, nếu kết quả là một danh sách có cùng kích thước với đầu vào, bạn không tìm cách giảm: Kết quả của việc giảm thường phải là một giá trị duy nhất. Thay vào đó, sử dụng map hoặc đơn giản là

[x for x in [1,2,3]] 
+2

tôi sẽ không xác định 'tmpf' theo cách này, vì nó có tác dụng phụ không mong muốn của việc sửa đổi initializer (đối số cuối cùng thành 'reduce'). – NPE

+0

@aix Thêm cảnh báo chống lại việc sử dụng 'reduce' để tạo danh sách. Bạn có thể chèn 'nếu len (x) == 0: x = []' trong 'tmpf', nhưng chỉ nhấn mạnh rằng' reduce' không phải là công cụ thích hợp cho công việc này. – phihag

0

Chỉ cần để giải thích các thông báo lỗi:

AttributeError: 'NoneType' object has no attribute 'append'

Khái niệm

reduce(lambda x,y: x.append(y), [1,2,3],[])

tương đương với

[].append(1).append(2).append(3)

Kể từ [].append(1) không trả lại một giá trị, tức là nó sẽ trả về None nó cố gắng để thực hiện (ở bước thứ hai)

None.append(2)

mà kết quả trong các thông báo lỗi Nonetype object has no attribute append