Статьи

Основы Python Lambdas

Многие языки программирования имеют понятие лямбда-функции. В Python лямбда-это анонимная функция или несвязанная функция. Синтаксис для них выглядит немного странно, но на самом деле он просто берет простую функцию и превращает ее в однострочник. Давайте посмотрим на обычную простую функцию для начала:

#----------------------------------------------------------------------
def doubler(number):
    return x*2

Все, что делает эта функция — это взять целое число и удвоить его. Технически, это также удвоит другие вещи, так как нет проверки типов, но это его цель. Теперь давайте превратим это в лямбда-функцию!

К счастью, превратить однострочную функцию в лямбду довольно просто. Вот как:

doubler = lambda x: x*2

Таким образом, лямбда работает во многом так же, как и функция. Для ясности, «x» — это аргумент, который вы передаете. Двоеточие выделяет список аргументов из возвращаемого значения или выражения. Поэтому, когда вы добираетесь до части «x * 2», это то, что возвращается. Давайте посмотрим на другой пример:

>>> poww = lambda i: i**2
>>> poww(2)
4
>>> poww(4)
16
>>> (lambda i: i**2)(6)
36

Здесь мы покажем, как создать лямбду, которая принимает входные данные и возводит их в квадрат. В сообществе Python есть некоторые аргументы относительно того, следует ли вам назначать лямбда-переменную. Причина в том, что когда вы называете лямбду, она перестает быть анонимной, и вы можете просто написать обычную функцию. Весь смысл лямбды в том, чтобы использовать ее один раз и выбросить. Последний пример выше показывает один способ анонимного вызова лямбды (т.е. использовать его один раз).

Кроме того, если вы назовете лямбду, то вы можете просто сделать это:

>>> def poww(i): return i**2
>>> poww(2)
4

Давайте двигаться дальше и посмотрим, как использовать лямбду в понимании списка!

Лямбды, списки и карта

Мне всегда было трудно придумать хорошие способы использования лямбд, кроме как использовать их для обратных вызовов. Поэтому я пошел искать другие варианты использования. Кажется, что некоторые люди любят использовать их в списках. Вот пара примеров:

>>> [(lambda x: x*3)(i) for i in range(5)]
[0, 3, 6, 9, 12]
>>> tripler = lambda x: x*3
>>> [tripler(i) for i in range(5)]
[0, 3, 6, 9, 12]

Первый пример немного неловкий. Хотя он вызывает лямбда анонимно, его также немного трудно читать. В следующем примере лямбда-переменная присваивается переменной, а затем мы называем ее так. Самое смешное в этом то, что в Python есть встроенный способ вызова функции с итерируемым вызовом map . Вот как вы обычно используете это:

map(function, interable)

И вот реальный пример использования нашей лямбда-функции из более раннего:

>>> map(tripler, range(5))
[0, 3, 6, 9, 12]

Конечно, в большинстве случаев лямбда настолько проста, что сделать то же самое в понимании списка, вероятно, проще:

>>> [x*3 for x in range(5)]
[0, 3, 6, 9, 12]

Другие способы использования лямбды

Мои читатели предложили некоторые другие способы использования лямбды. Первый пример возвращает лямбду из вызова функции:

>>> def increment(n): 
        return lambda(x): x + n
>>> i = increment(5)
>>> i(2)
7

Здесь мы создаем функцию, которая будет увеличивать все, что мы даем ей, на 5. Один из моих других читателей предложил передать лямбду в сортированную функцию Python :

sorted(list, key=lambda i: i.address)

Идея здесь состоит в том, чтобы отсортировать список объектов с помощью свойства «адрес». Тем не менее, я по-прежнему считаю, что лучший вариант использования лямбды — это обратные вызовы событий, поэтому давайте посмотрим, как их использовать для этого с помощью Tkinter.

Использование лямбды для обратных вызовов

lambda_tk

Tkinter — это инструментарий GUI, который поставляется с Python. Когда вы хотите взаимодействовать с вашим пользовательским интерфейсом, вы обычно используете клавиатуру и мышь. Эти взаимодействия работают через события, где и появляется лямбда. Давайте создадим простой пользовательский интерфейс, чтобы вы могли видеть, как лямбда используется в Tkinter!

import Tkinter as tk

########################################################################
class App:
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        frame = tk.Frame(parent)
        frame.pack()

        print_btn = tk.Button(frame, text='Print',
                              command=lambda: self.onPrint('Print'))
        print_btn.pack(side=tk.LEFT)

        close_btn = tk.Button(frame, text='close', command=frame.quit)
        close_btn.pack(side=tk.LEFT)

    #----------------------------------------------------------------------
    def onPrint(self, num):
        print "You just printed something"

#----------------------------------------------------------------------
if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()

Итак, у нас есть простой пользовательский интерфейс с двумя кнопками. Одна кнопка вызывает метод onPrint с использованием лямбды, а другая использует метод Tkinter для закрытия приложения. Как видите, Tkinter использует лямбду так, как это было задумано. Лямбда здесь используется один раз, а затем выбрасывается. Нет ссылки на него, кроме как нажатием кнопки.

Завершение

Как, вероятно, знают мои давние читатели, я написал о лямбде в другой статье более пяти лет назад. В то время я не особо пользовался лямбдами и, честно говоря, до сих пор не пользуюсь. Они — отличная особенность языка, но после программирования на Python в течение более 9 лет я почти никогда не обнаруживал необходимости их использования, особенно в том смысле, как они предназначены для использования. Но каждому свое. Конечно, нет ничего плохого в использовании лямбд, но я надеюсь, что вы найдете эту статью полезной для выяснения, действительно ли вам нужно использовать их в своей работе.