Hàm python max sử dụng biểu thức 'key' và lambda


180

Tôi đến từ nền tảng OOP và cố gắng học trăn. Tôi đang sử dụng maxhàm sử dụng biểu thức lambda để trả về thể hiện của loại Playercó tối đa totalScoretrong danh sách players.

def winner():
    w = max(players, key=lambda p: p.totalScore)

Hàm trả về đúng thể hiện của loại Playercó tối đa totalScore. Tôi bối rối về ba điều sau đây:

  1. Làm thế nào để các maxcông việc chức năng? Các đối số nó đang dùng là gì? Tôi đã xem tài liệu nhưng không hiểu.
  2. Việc sử dụng từ khóa keytrong chức năng tối đa là gì? Tôi biết nó cũng được sử dụng trong bối cảnh của sortchức năng
  3. Ý nghĩa của biểu thức lambda? Làm thế nào để đọc chúng? Họ làm việc như thế nào?

Đây là tất cả các câu hỏi khái niệm rất noobish nhưng sẽ giúp tôi hiểu ngôn ngữ. Nó sẽ giúp nếu bạn có thể đưa ra ví dụ để giải thích. Cảm ơn


Phiên bản Python nào?
charmlessCoin

2
Bạn đã tham khảo tài liệu ?
Inbar Rose

@charmlessCoin trăn 2.7.5
Vijay

2
@InbarRose Tôi đã kiểm tra tài liệu cho chức năng tối đa. Không thực sự hiểu nó.
Vijay

10
@InbarRose Trang này thực sự là kết quả hàng đầu trên Google python max lambdavà có lẽ thực sự hữu ích hơn cho người dùng mới.
Đánh dấu

Câu trả lời:


277

lambda là một hàm ẩn danh, nó tương đương với:

def func(p):
   return p.totalScore     

Bây giờ maxtrở thành:

max(players, key=func)

Nhưng vì các defcâu lệnh là các câu lệnh ghép, chúng không thể được sử dụng khi cần một biểu thức, đó là lý do tại sao đôi khi lambdachúng được sử dụng.

Lưu ý rằng lambdatương đương với những gì bạn đưa vào một tuyên bố trả về của a def. Vì vậy, bạn không thể sử dụng các câu lệnh bên trong a lambda, chỉ các biểu thức được cho phép.


Không gì maxlàm gì?

tối đa (a, b, c, ... [, key = func]) -> giá trị

Với một đối số lặp duy nhất, trả về mục lớn nhất của nó. Với hai hoặc nhiều đối số, trả về đối số lớn nhất.

Vì vậy, nó chỉ đơn giản trả về đối tượng là lớn nhất.


Làm thế nào để keylàm việc?

Theo mặc định trong Python 2 keyso sánh các mục dựa trên một bộ quy tắc dựa trên loại đối tượng (ví dụ: một chuỗi luôn lớn hơn một số nguyên).

Để sửa đổi đối tượng trước khi so sánh hoặc so sánh dựa trên một thuộc tính / chỉ mục cụ thể, bạn phải sử dụng keyđối số.

Ví dụ 1:

Một ví dụ đơn giản, giả sử bạn có một danh sách các số ở dạng chuỗi, nhưng bạn muốn so sánh các mục đó theo giá trị nguyên của chúng.

>>> lis = ['1', '100', '111', '2']

Ở đây maxso sánh các mục sử dụng các giá trị ban đầu của chúng (các chuỗi được so sánh theo từ vựng để bạn nhận '2'làm đầu ra):

>>> max(lis)
'2'

Để so sánh các mục theo giá trị số nguyên của chúng, hãy sử dụng keymột cách đơn giản lambda:

>>> max(lis, key=lambda x:int(x))  # compare `int` version of each item
'111'

Ví dụ 2: Áp dụng maxvào danh sách các bộ dữ liệu.

>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]

Theo mặc định maxsẽ so sánh các mục theo chỉ mục đầu tiên. Nếu chỉ mục đầu tiên giống nhau thì nó sẽ so sánh chỉ mục thứ hai. Như trong ví dụ của tôi, tất cả các mục có một chỉ mục đầu tiên duy nhất, vì vậy bạn sẽ nhận được đây là câu trả lời:

>>> max(lis)
(4, 'e')

Nhưng, nếu bạn muốn so sánh từng mục theo giá trị tại chỉ mục 1 thì sao? Đơn giản: sử dụng lambda:

>>> max(lis, key = lambda x: x[1])
(-1, 'z')

So sánh các mục trong một lần lặp có chứa các đối tượng thuộc loại khác nhau :

Danh sách với các mặt hàng hỗn hợp:

lis = ['1','100','111','2', 2, 2.57]

Trong Python 2 có thể so sánh các mục của hai loại khác nhau :

>>> max(lis)  # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x))  # compare integer version of each item
'111'

Nhưng trong Python 3, bạn không thể làm điều đó nữa :

>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
  File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
    max(lis)
TypeError: unorderable types: int() > str()

Nhưng điều này hoạt động, vì chúng ta đang so sánh phiên bản số nguyên của từng đối tượng:

>>> max(lis, key=lambda x: int(x))  # or simply `max(lis, key=int)`
'111'

Tôi nghĩ rằng điều này là cũ, nhưng tôi đã có một câu hỏi liên quan đến điều này. Tôi thấy đối với hàm lambda, biến x hoặc i hoặc bất cứ thứ gì khác luôn đại diện cho giá trị tại chỉ mục đó trong danh sách. Việc lặp này được thực hiện bởi hàm max hay bởi lambda? Các hàm lambda luôn lặp đi lặp lại trên các giá trị có thể? Ví dụ: lengths = map(lambda word: len(word), words)nơi words=['It', 'is', 'raining', 'cats', 'and', 'dogs']tôi thấy rằng lambda đang lặp lại trên mỗi từ trong danh sách. Nó luôn luôn làm điều này?
Mo2

1
@ Mo2 Lặp được thực hiện bởi maxkhông lambda( keyarg là tùy chọn) và trong quá trình lặp, mỗi mục được truyền cho hàm được chỉ định trong keyvà sau đó giá trị được trả về được sử dụng để so sánh.
Ashwini Chaudhary

2
Chỉ dành cho những người đến đây bằng cách googling "tham số khóa tối đa". max(lis, key=lambda x:int(x))có thể được đơn giản hóa như max(lis, key=int). Python có hàm dựng sẵn, int (). Tương tự, bạn có thể sử dụng bất kỳ hàm dựng sẵn nào khác làm keyđối số. Ví dụ bạn có thể lấy chuỗi dài nhất từ lis=['a', 'aa', 'aaa']bằngmax(lis, key=len)
YOUNG

1
@YOUNG Chúng ta có thể sử dụng bất kỳ chức năng như là đối số then chốt không chỉ được xây dựng trong chức năng, điều kiện duy nhất là chức năng nên chấp nhận các mục được truyền cho nó bởi max, min, sortedvv đúng cách. Thêm vào đó tôi đã đề cập max(lis, key=int)ngay ở cuối. :-)
Ashwini Chaudhary

@Ashwini Chaudhary .. giả sử Nếu tôi có một danh sách như [1,2,3,4,5]. ở đây tất cả các mặt hàng là khác nhau. Tôi đang sử dụng hàm max (set (mylist), key = mylist.count) để tìm các mục thường xuyên nhất. vì trong trường hợp này không có yếu tố nào được lặp lại. nó đang trả lại hàng thấp nhất Chúng ta có thể làm một cái gì đó để nó trả về 0 hoặc null trong trường hợp đó.
vikrant rana

12

Phiên bản đơn giản hóa mạnh mẽ của max:

def max(items, key=lambda x: x):
    current = item[0]
    for item in items:
        if key(item) > key(current):
            current = item
    return current

Về lambda:

>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5

>>> times_two = lambda x: 2*x
>>> times_two(2)
4

10

Hàm max hoạt động như thế nào?

Nó tìm kiếm mục "lớn nhất" trong một lần lặp. Tôi sẽ cho rằng bạn có thể tra cứu đó là gì, nhưng nếu không, đó là thứ bạn có thể lặp lại, tức là một danh sách hoặc chuỗi.

Việc sử dụng khóa từ khóa trong chức năng tối đa là gì? Tôi biết nó cũng được sử dụng trong ngữ cảnh của chức năng sắp xếp

Keylà một hàm lambda sẽ cho biết maxcác đối tượng trong iterable lớn hơn các đối tượng khác. Nói nếu bạn đang sắp xếp một số đối tượng mà bạn tự tạo, và không phải thứ gì đó rõ ràng, như số nguyên.

Ý nghĩa của biểu thức lambda? Làm thế nào để đọc chúng? Họ làm việc như thế nào?

Đó là một câu hỏi lớn hơn. Nói một cách đơn giản, lambda là một chức năng bạn có thể vượt qua và có các đoạn mã khác sử dụng nó. Lấy ví dụ này:

def sum(a, b, f):
    return (f(a) + f(b))

Điều này có hai đối tượng, ab, và một chức năng f. Nó gọi f()từng đối tượng, sau đó thêm chúng lại với nhau. Vì vậy, nhìn vào cuộc gọi này:

>>> sum(2, 2, lambda a:  a * 2)
8

sum()mất 2, và gọi biểu thức lambda trên nó. Vì vậy, f(a)trở thành 2 * 2, mà trở thành 4. Sau đó, nó làm điều này cho bvà thêm hai cái lại với nhau.

Nói một cách không đơn giản, lambdas đến từ tính toán lambda, đó là ý tưởng về một hàm trả về một hàm; một khái niệm toán học rất hay để thể hiện tính toán. Bạn có thể đọc về điều đó ở đây , và sau đó thực sự hiểuở đây .

Có lẽ tốt hơn để đọc về điều này nhiều hơn một chút, vì lambdas có thể gây nhầm lẫn, và không rõ ràng ngay lập tức chúng hữu ích như thế nào. Kiểm tra tại đây .


7

maxchức năng được sử dụng để có được tối đa ra khỏi một iterable.

Các trình vòng lặp có thể là danh sách, bộ dữ liệu, đối tượng dict, v.v. Hoặc thậm chí các đối tượng tùy chỉnh như trong ví dụ bạn cung cấp.

max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.

Vì vậy, key=funcvề cơ bản cho phép chúng ta truyền một đối số tùy chọn keycho hàm trên cơ sở mà trình lặp / đối số đã cho được sắp xếp và trả về mức tối đa.

lambdalà một từ khóa python hoạt động như một chức năng giả. Vì vậy, khi bạn truyền playerđối tượng cho nó, nó sẽ trở lại player.totalScore. Do đó, iterable được chuyển qua hàm maxsẽ sắp xếp theo key tổng số điểm của các playerđối tượng được cung cấp cho nó & sẽ trả về playerngười có mức tối đa totalScore.

Nếu không có keyđối số nào được cung cấp, mức tối đa được trả về theo thứ tự Python mặc định.

Ví dụ -

max(1, 3, 5, 7)
>>>7
max([1, 3, 5, 7])
>>>7

people = [('Barack', 'Obama'), ('Oprah', 'Winfrey'), ('Mahatma', 'Gandhi')]
max(people, key=lambda x: x[1])
>>>('Oprah', 'Winfrey')

6

Theo tài liệu :

max (iterable [, key])
max (arg1, arg2, * args [, key])
Trả về mục lớn nhất trong một lần lặp hoặc lớn nhất trong hai hoặc nhiều đối số.

Nếu một đối số vị trí được cung cấp, iterable phải là một iterable không trống (chẳng hạn như một chuỗi, tuple hoặc danh sách không trống). Mục lớn nhất trong vòng lặp được trả lại. Nếu hai hoặc nhiều đối số vị trí được cung cấp, lớn nhất trong số các đối số vị trí được trả về.

Đối số khóa tùy chọn chỉ định hàm đặt hàng một đối số như được sử dụng cho list.sort (). Đối số khóa, nếu được cung cấp, phải ở dạng từ khóa (ví dụ: max (a, b, c, key = func)).

Điều này đang nói là trong trường hợp của bạn, bạn đang cung cấp một danh sách, trong trường hợp này players. Sau đó, maxhàm sẽ lặp lại tất cả các mục trong danh sách và so sánh chúng với nhau để có được "mức tối đa".

Như bạn có thể tưởng tượng, với một đối tượng phức tạp như playerxác định giá trị của nó để so sánh là khó khăn, vì vậy bạn được đưa ra keyđối số để xác định cách maxhàm sẽ quyết định giá trị của mỗi giá trị player. Trong trường hợp này, bạn đang sử dụng một hàm lambda để nói "cho mỗi ptrong playersget p.totalscorevà sử dụng đó như là giá trị của mình để so sánh".


3

maxđược xây dựng trong hàm lấy đối số đầu tiên iterable(như danh sách hoặc bộ dữ liệu)

đối số từ khóa keycó giá trị mặc định Nonenhưng nó chấp nhận hàm để đánh giá, coi nó như là trình bao bọc để đánh giá khả năng lặp lại dựa trên hàm

Xem xét từ điển ví dụ này:

d = {'aim':99, 'aid': 45, 'axe': 59, 'big': 9, 'short': 995, 'sin':12, 'sword':1, 'friend':1000, 'artwork':23}

Ví dụ:

>>> max(d.keys())
'sword'

Như bạn có thể thấy nếu bạn chỉ vượt qua iterable mà không có kwarg (một hàm để key) thì nó sẽ trả về giá trị tối đa của khóa (theo bảng chữ cái)

Ví dụ. Thay vì tìm giá trị tối đa của khóa theo thứ tự bảng chữ cái, bạn có thể cần tìm khóa tối đa theo độ dài của khóa:

>>>max(d.keys(), key=lambda x: len(x))
'artwork'

trong ví dụ này, hàm lambda đang trả về độ dài của khóa sẽ được lặp lại do đó trong khi đánh giá các giá trị thay vì xem xét theo thứ tự bảng chữ cái, nó sẽ theo dõi độ dài tối đa của khóa và trả về khóa có độ dài tối đa

Ví dụ.

>>> max(d.keys(), key=lambda x: d[x])
'friend'

trong ví dụ này, hàm lambda đang trả về giá trị của khóa từ điển tương ứng có giá trị tối đa

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.