Анонимные функции python: Как использовать в Python лямбда-функции

Содержание

Функции и их аргументы | Python 3 для начинающих и чайников

В этой статье я планирую рассказать о функциях, именных и анонимных, инструкциях def, return и lambda, обязательных и необязательных аргументах функции, функциях с произвольным числом аргументов.

Именные функции, инструкция def

Функция в python — объект, принимающий аргументы и возвращающий значение. Обычно функция определяется с помощью инструкции def.

Определим простейшую функцию:

def add(x, y):
    return x + y

Инструкция return говорит, что нужно вернуть значение. В нашем случае функция возвращает сумму x и y.

Теперь мы ее можем вызвать:

>>> add(1, 10)
11
>>> add('abc', 'def')
'abcdef'

Функция может быть любой сложности и возвращать любые объекты (списки, кортежи, и даже функции!):

>>> def newfunc(n):
...     def myfunc(x):
...         return x + n
...     return myfunc
...
>>> new = newfunc(100)  # new - это функция
>>> new(200)
300

Функция может и не заканчиваться инструкцией return, при этом функция вернет значение None:

>>> def func():
...     pass
...
>>> print(func())
None

Аргументы функции

Функция может принимать произвольное количество аргументов или не принимать их вовсе. Также распространены функции с произвольным числом аргументов, функции с позиционными и именованными аргументами, обязательными и необязательными.

>>> def func(a, b, c=2): # c - необязательный аргумент
...     return a + b + c
...
>>> func(1, 2)  # a = 1, b = 2, c = 2 (по умолчанию)
5
>>> func(1, 2, 3)  # a = 1, b = 2, c = 3
6
>>> func(a=1, b=3)  # a = 1, b = 3, c = 2
6
>>> func(a=3, c=6)  # a = 3, c = 6, b не определен
Traceback (most recent call last):
  File "", line 1, in
    func(a=3, c=6)
TypeError: func() takes at least 2 arguments (2 given)

Функция также может принимать переменное количество позиционных аргументов, тогда перед именем ставится *:

>>> def func(*args):
...     return args
...
>>> func(1, 2, 3, 'abc')
(1, 2, 3, 'abc')
>>> func()
()
>>> func(1)
(1,)

Как видно из примера, args — это кортеж из всех переданных аргументов функции, и с переменной можно работать также, как и с кортежем.

Функция может принимать и произвольное число именованных аргументов, тогда перед именем ставится **:

>>> def func(**kwargs):
...     return kwargs
...
>>> func(a=1, b=2, c=3)
{'a': 1, 'c': 3, 'b': 2}
>>> func()
{}
>>> func(a='python')
{'a': 'python'}

В переменной kwargs у нас хранится словарь, с которым мы, опять-таки, можем делать все, что нам заблагорассудится.

Анонимные функции, инструкция lambda

Анонимные функции могут содержать лишь одно выражение, но и выполняются они быстрее. Анонимные функции создаются с помощью инструкции lambda. Кроме этого, их не обязательно присваивать переменной, как делали мы инструкцией def func():

>>> func = lambda x, y: x + y
>>> func(1, 2)
3
>>> func('a', 'b')
'ab'
>>> (lambda x, y: x + y)(1, 2)
3
>>> (lambda x, y: x + y)('a', 'b')
'ab'

lambda функции, в отличие от обычной, не требуется инструкция return, а в остальном, ведет себя точно так же:

>>> func = lambda *args: args
>>> func(1, 2, 3, 4)
(1, 2, 3, 4)

Функциональное программирование на Python для самых маленьких — Часть 1 — Lambda Функция

Я решил написать эту серию статей, ибо считаю, что никто не должен сталкиваться с той стеной непонимания, с которой столкнулся когда-то я.

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


Небольшое введение


Для начала, давайте разберемся, что такое функциональное программирование, в чем его особенности, зачем оно было придумано, а также где и как его использовать. Стоп… А зачем? Об этом написаны тонны материалов, да и в этой статье судя по всему эта информация не особо нужна. Эта статья написана для того, чтобы читатели научились разбираться в коде, который написан в функциональном стиле. Но если вы все-таки хотите разобраться в истории Функционального Программирования и в том, как оно работает под капотом, то советую вам почитать о таких вещах, как
  • Чистая Функция
  • Функции высшего порядка

Давайте кратко разберемся в этих двух понятиях прежде чем продолжим.

Чистая Функция — Функция которая является детерминированной и не обладает никакими побочными эффектами.

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

Пример детерминированной функции

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

print(sum(3,6))
print(sum(3,6))
print(sum(3,6))

>>>9
>>>9
>>>9

И пример не детерминированной:
from datetime import date

todays_weekday = date.today().weekday()
def sum(a,b):
  if todays_weekday == 1:
    result = a+b
    print(f'sum is {result} and result class is {type(result)}')
  else:
    result = str(a+b)
    print(f'sum is {result} and result class is {type(result)}')

sum(4,5)
todays_weekday = 4
sum(4,5)

>>>sum is 9 and result class is <class 'int'>
>>>sum is 9 and result class is <class 'str'>

Каждый раз при смене дня недели (который не является аргументом функции) функция выдает разные результаты.

Самый очевидный пример не детерминированной функции это random:

import random
print(random.random())
print(random.random())
print(random.random())

>>>0.5002395668892657
>>>0.8837128676460416
>>>0.5308851462814731

Второе важное качество чистой функции это отсутствие побочных эффектов.

Покажем наглядно:

my_list = [32,3,50,2,29,43]

def sort_by_sort(li):
  li.sort()
  print(li)

sort_by_sort(my_list)
print(my_list)

>>>[2, 3, 29, 32, 43, 50]
>>>[2, 3, 29, 32, 43, 50]

Функция sort_by_sort имеет побочные эффекты потому что изменяет исходный список элементов и выводит что то в консоль.
my_list = [32,3,50,2,29,43]

def sort_by_sorted(li):
  return sorted(li)

print(sort_by_sorted(my_list))
print(my_list)

>>>[2, 3, 29, 32, 43, 50]
>>>[32, 3, 50, 2, 29, 43]

В отличии от предыдущего примера функция sort_by_sorted не меняет исходного массива и возвращает результат не выводя его в консоль самостоятельно.

Чистые функции хороши тем что:

  • Они проще читаются
  • Они проще поддерживаются
  • Они проще тестируются
  • Они не зависят от того в каком порядке их вызывать

Функциональное программирование можно охарактеризовать тем что в нем используются только чистые функции.
Функции высшего порядка — в программировании функция, принимающая в качестве аргументов другие функции или возвращающая другую функцию в качестве результата.

Пример ФВП:
def func(num):
  return num**2

def higher_order_func(fun, num):
  return fun(num)+fun(num)

print(func(4))
print(higher_order_func(func,4))

>>>16
>>>32

С основами чуть чуть разобрались и теперь перейдем к следующему шагу.

Итак, начнем


Для начала надо понять следующее — что такое Функциональное Программирование вообще. Лично я знаю две самые часто упоминаемые парадигмы в повседневном программировании — это ООП и ФП.

Если упрощать совсем и объяснять на пальцах, то описать эти две парадигмы можно следующим образом:

  • ООП — это Объектно Ориентированное Программирование — подход к программированию, при использовании которого объекты можно передавать в качестве параметров и использовать их в качестве значений.
  • По такой логике можно установить, что ФП — подход к программированию, при использовании которого функции можно передавать другим функциям в качестве параметров и использовать функции в качестве значений, возвращаемых другими функциями… Ответ скрыт в самом названии.

Как говорил мой любимый учитель zverok Виктор Шепелев: «Вся работа в программировании — это работа с данными. Взял какие-то данные, поигрался с ними и вернул обратно.»

Это относится и к ФП — взял какие-то данные, взял какую-то функцию, поигрался с ними и выдал что-то на выходе.

Не стану расписывать всё, иначе это будет оооочень долго. Цель данной статьи — помочь разобраться, а не объяснить, как и что работает, поэтому тут мы рассмотрим основные функции из ФП.

В большинстве своем ФП (как я его воспринимаю) — это просто упрощенное написание кода. Любой код, написанный в функциональном стиле, может быть довольно легко переписан в обычном стиле без потери качества, но более примитивно. Цель ФП заключается в том, чтобы писать код более простой, понятный и который легче поддерживать, а также который занимает меньше памяти, ну и куда же без этого — разумеется, главная вечная мораль программирования — DRY (Don’t Repeat Yourself — Не повторяйся).

Сейчас мы с вами разберем одну из основных функций, которая применяется в ФП — Lambda функцию.

В следующих статьях мы разберем такие функции как Map, Zip, Filter и Reduce.

Lambda функция


Lambda — это инструмент в python и других языках программирования для вызова анонимных функций. Многим это скорее всего ничего не скажет и никак не прояснит того, как она работает, поэтому я расскажу вам просто механизм работы lambda выражений.

Все очень просто.

Рассмотрим пример. Например, нам надо написать функцию которая бы считала площадь круга при известном радиусе.

Формула площади круга это

S = pi*(r**2)

где
S — это площадь круга
pi — математическая константа равная 3.14 которую мы получим из стандартной библиотеки Math

r — радиус круга — единственная переменная которую мы будем передавать нашей функции

Теперь оформим это все в python:

import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

# Пишем функцию которая будет вычислять площадь круга по заданному радиусу в обычном варианте записи
def area_of_circle_simple(radius):
  return pi_const*(radius**2)

print(area_of_circle_simple(5))
print(area_of_circle_simple(12))
print(area_of_circle_simple(26))
>>>78.5
>>>452.16
>>>2122.64

Вроде бы неплохо, но это всё может выглядеть куда круче, если записывать это через lambda:
import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака 
# после запятой иначе она будет выглядеть 
# как 3.141592653589793 а нам это будет неудобно

print((lambda radius: pi_const*(radius**2))(5))
print((lambda radius: pi_const*(radius**2))(12))
print((lambda radius: pi_const*(radius**2))(26))

>>>78.5
>>>452.16
>>>2122.64

Чтобы было понятнее, анонимный вызов функции подразумевает то, что вы используете её, нигде не объявляя, как в примере выше.

Лямбда функция работает по следующему принципу


print((lambda перечисляются аргументы через запятую : что то с ними делается)(передаем аргументы))

>>>получаем результат того что находится после двоеточия строкой выше

Рассмотрим пример с двумя входными аргументами. Например, нам надо посчитать объем конуса по следующей формуле:

V = (height*pi_const*(radius**2))/3

Запишем это все в python:

import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

#Формула объема конуса в классической форме записи
def cone_volume(height, radius):
  volume = (height*pi_const*(radius**2))/3
  return volume

print(cone_volume(3, 10))

>>>314.0

А теперь как это будет выглядеть в lambda форме:
import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

print((lambda height, radius : (height*pi_const*(radius**2))/3)(3, 10))

>>>314.0

Количество переменных здесь никак не ограничено. Для примера посчитаем объем усеченного конуса, где у нас учитываются 3 разные переменные.

Объем усеченного конуса считается по формуле:

V = (pi_const*height*(r1**2 + r1*r2 + r2**2))/3

И вот, как это будет выглядеть в python классически:

import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

#Формула объема усеченного конуса в классической записи
def cone_volume(h,r1,r2):
  return (pi_const * h * (r1 ** 2 + r1 * r2 + r2 ** 2))/3

print(cone_volume(12, 8, 5))
print(cone_volume(15, 10, 6))
print(cone_volume(20, 12, 9))

>>>1620.24
>>>3077.20
>>>6970.8

А теперь покажем, как это будет выглядеть с lambda:
import math #Подключаем библиотеку math

pi_const = round(math.pi, 2) #округляем pi до второго знака после запятой иначе она будет выглядеть как 3.141592653589793 а нам это будет неудобно

print((lambda height, radius1, radius2 : (height*pi_const*(radius1**2 + radius1*radius2 + radius2**2))/3)(12, 8, 5))
print((lambda height, radius1, radius2 : (height*pi_const*(radius1**2 + radius1*radius2 + radius2**2))/3)(15, 10, 6))
print((lambda height, radius1, radius2 : (height*pi_const*(radius1**2 + radius1*radius2 + radius2**2))/3)(20, 12, 9))

>>>1620.24
>>>3077.20
>>>6970.8

После того, как мы разобрались, как работает lambda функция, давайте разберем ещё кое-что интересное, что можно делать с помощью lambda функции, что может оказаться для вас весьма неожиданным — Сортировку.

Сортировать одномерные списки в python с помощью lambda довольно глупо — это будет выглядеть, как бряцание мускулами там, где оно совсем не нужно.

Ну серьезно допустим, у нас есть обычный список (не важно состоящий из строк или чисел) и нам надо его отсортировать — тут же проще всего использовать встроенную функцию sorted(). И в правду, давайте посмотрим на это.

new_int_list = [43,23,56,75,12,32] # Создаем список чисел
print(sorted(new_int_list)) # Сортируем список чисел
new_string_list = ['zum6z', 'yybt0', 'h2uwq', '2k9f9', 'hin9h', 'b0p0m'] # Создаем список строк
print(sorted(new_string_list)) # Сортируем список строк

>>>[12, 23, 32, 43, 56, 75]
>>>['2k9f9', 'b0p0m', 'h2uwq', 'hin9h', 'yybt0', 'zum6z']

В таких ситуациях, действительно, хватает обычного sorted() (ну или sort(), если вам нужно изменить текущий список на месте без создания нового, изменив исходный).

Но что, если нужно отсортировать список словарей по разным ключам? Тут может быть запись как в классическом стиле, так и в функциональном. Допустим, у нас есть список книг вселенной Песни Льда и Пламени с датами их публикаций и количеством страниц в них.

Как всегда, начнем с классической записи.

# Создали список из словарей книг
asoiaf_books = [
  {'title' : 'Game of Thrones', 'published' : '1996-08-01', 'pages': 694},
  {'title' : 'Clash of Kings', 'published' : '1998-11-16', 'pages': 761},
  {'title' : 'Storm of Swords', 'published' : '2000-08-08', 'pages': 973},
  {'title' : 'Feast for Crows', 'published' : '2005-10-17', 'pages': 753},
  {'title' : 'Dance with Dragons', 'published' : '2011-07-12', 'pages': 1016}
]

# Функция по получению названия книги
def get_title(book):
    return book.get('title')

# Функция по получению даты публикации книги
def get_publish_date(book):
    return book.get('published')

# Функция по получению количества страниц в книге
def get_pages(book):
    return book.get('pages')

# Сортируем по названию
asoiaf_books.sort(key=get_title)
for book in asoiaf_books:
  print(book)
print('-------------')
# Сортируем по датам
asoiaf_books.sort(key=get_publish_date)
for book in asoiaf_books:
  print(book)
print('-------------')
# Сортируем по количеству страниц
asoiaf_books.sort(key=get_pages)
for book in asoiaf_books:
  print(book)

>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>-------------
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}
>>>-------------
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}

А теперь перепишем это все через lambda функцию:
# Создали список из словарей книг
asoiaf_books = [
  {'title' : 'Game of Thrones', 'published' : '1996-08-01', 'pages': 694},
  {'title' : 'Clash of Kings', 'published' : '1998-11-16', 'pages': 761},
  {'title' : 'Storm of Swords', 'published' : '2000-08-08', 'pages': 973},
  {'title' : 'Feast for Crows', 'published' : '2005-10-17', 'pages': 753},
  {'title' : 'Dance with Dragons', 'published' : '2011-07-12', 'pages': 1016}
]

# Сортируем по названию
for book in sorted(asoiaf_books, key=lambda book: book.get('title')):
  print(book)

print('-------------')

# Сортируем по датам
for book in sorted(asoiaf_books, key=lambda book: book.get('published')):
  print(book)

print('-------------')

# Сортируем по количеству страниц
for book in sorted(asoiaf_books, key=lambda book: book.get('pages')):
  print(book)

>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>-------------
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}
>>>-------------
>>>{'title': 'Game of Thrones', 'published': '1996-08-01', 'pages': 694}
>>>{'title': 'Feast for Crows', 'published': '2005-10-17', 'pages': 753}
>>>{'title': 'Clash of Kings', 'published': '1998-11-16', 'pages': 761}
>>>{'title': 'Storm of Swords', 'published': '2000-08-08', 'pages': 973}
>>>{'title': 'Dance with Dragons', 'published': '2011-07-12', 'pages': 1016}

Таким образом, lambda функция хорошо подходит для сортировки многомерных списков по разным параметрам.

Если вы повторите весь этот код самостоятельно, написав его сами, то я уверен, что с этого момента вы сможете сказать, что отныне вы понимаете, как работают lambda выражения, и сможете применять их в работе.

Но где же тут та самая экономия места, времени и памяти? Экономится максимум пара строк.

И вот тут мы подходим к реально интересным вещам.

Которые разберем в следующей статье, где мы обсудим map функцию.

UPD: По многочисленным просьбам, расставил знаки препинания.

Lambda в Python для начинающих: синтаксис, аргументы, применение

Предыдущий урок: Функции в Python

Лямбда-функция — это небольшая анонимная функция. Она может принимать любое количество аргументов, но в то же время иметь только одно выражение.

Синтаксис

lambda аргументы : выражение
После выполнения выражения — возвращается результат. Лямбда-функции могут принимать любое количество аргументов.
lambda умножает аргумент a на аргумент b и выводит результат:

x = lambda a, b: a * b
print(x(5,  6))

Вывод:

30

А эта функция суммирует аргументы a, b и c и выводит результат:

x = lambda a, b, c: a + b + c
print(x(5, 6, 2))

Вывод:

13

Зачем использовать лямбда-функции?

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

def myfunc(n):  
    return lambda a: a * n

Используйте это определение функции для создания функции, которая всегда удваивает число, которое вы отправляете:

def myfunc(n):
    return lambda a: a * n


mydoubler = myfunc(2)
print(mydoubler(11))

Вывод:

22

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

def myfunc(n):
    return lambda a: a * n


mytripler = myfunc(3)
print(mytripler(11))

Вывод:

33

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

def myfunc(n):
    return lambda  a: a * n


mydoubler = myfunc(2)
mytripler = myfunc(3)
print(mydoubler(11))
print(mytripler(11))

Вывод:

22
33

Используйте lambda-функцию, когда анонимная функция нужна в определенной части кода, но не по всем скрипте.

Далее: Массивы

синтаксис, логика и применение ~ PythonRu

Введение

Определение

Вот пример простой функции:

def compute_surface(radius):
    from math import pi
    return pi * radius * radius

Для определения функции нужно всего лишь написать ключевое слово def перед ее именем, а после — поставить двоеточие. Следом идет блок инструкций.

Последняя строка в блоке инструкций может начинаться с return, если нужно вернуть какое-то значение. Если инструкции return нет, тогда по умолчанию функция будет возвращать объект None. Как в этом примере:

i = 0
def increment():
    global i
    i += 1

Функция инкрементирует глобальную переменную i и возвращает None (по умолчанию).

Вызовы

Для вызова функции, которая возвращает переменную, нужно ввести:

surface = compute_surface(1.)

Для вызова функции, которая ничего не возвращает:

increment()

Еще

Функцию можно записать в одну строку, если блок инструкций представляет собой простое выражение:

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

Функции могут быть вложенными:

def func1(a, b):

    def inner_func(x):
        return x*x*x

    return inner_func(a) + inner_func(b)

Функции — это объекты, поэтому их можно присваивать переменным.

Инструкция return

Возврат простого значения

Аргументы можно использовать для изменения ввода и таким образом получать вывод функции. Но куда удобнее использовать инструкцию return, примеры которой уже встречались ранее. Если ее не написать, функция вернет значение None.

Возврат нескольких значений

Пока что функция возвращала только одно значение или не возвращала ничего (объект None). А как насчет нескольких значений? Этого можно добиться с помощью массива. Технически, это все еще один объект. Например:

def stats(data):
    """данные должны быть списком"""
    _sum = sum(data) 
    mean = sum / float(len(data)) 
    variance = sum([(x-mean(data))**2/len(data) for x in data])
    return mean,variance   

m, v = stats([1, 2, 1])

Аргументы и параметры

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

Параметр — это имя в списке параметров в первой строке определения функции. Он получает свое значение при вызове. Аргумент — это реальное значение или ссылка на него, переданное функции при вызове. В этой функции:

def sum(x, y):
    return x + y

x и y — это параметры, а в этой:

sum(1, 2)

1 и 2 — аргументы.

При определении функции параметры со значениями по умолчанию нужно указывать до позиционных аргументов:

def compute_surface(radius, pi=3.14159):
    return pi * radius * radius

Если использовать необязательный параметр, тогда все, что указаны справа, должны быть параметрами по умолчанию.

Выходит, что в следующем примере допущена ошибка:

def compute_surface(radius=1, pi):
    return pi * radius * radius

Для вызовов это работает похожим образом. Сначала нужно указывать все позиционные аргументы, а только потом необязательные:

S = compute_surface(10, pi=3.14)

На самом деле, следующий вызов корректен (можно конкретно указывать имя позиционного аргумента), но этот способ не пользуется популярностью:

S = compute_surface(radius=10, pi=3.14)

А этот вызов некорректен:

S = compute_surface(pi=3.14, 10)

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

def compute_surface2(radius=1, pi=3.14159):
    return pi * radius * radius
S = compute_surface2(radius=1, pi=3.14)
S = compute_surface2(pi=3.14, radius=10.)
S = compute_surface2(radius=10.)

Можно не указывать ключевые слова, но тогда порядок имеет значение. Он должен соответствовать порядку параметров в определении:

S = compute_surface2(10., 3.14)
S = compute_surface2(10.)

Если ключевые слова не используются, тогда нужно указывать все аргументы:

def f(a=1,b=2, c=3):
    return a + b + c

Второй аргумент можно пропустить:

f(1,,3)

Чтобы обойти эту проблему, можно использовать словарь:

params = {'a':10, 'b':20}
S = f(**params)

Значение по умолчанию оценивается и сохраняется только один раз при определении функции (не при вызове). Следовательно, если значение по умолчанию — это изменяемый объект, например, список или словарь, он будет меняться каждый раз при вызове функции. Чтобы избежать такого поведения, инициализацию нужно проводить внутри функции или использовать неизменяемый объект:

def inplace(x, mutable=[]):
   mutable.append(x)
   return mutable
res = inplace(1)
res = inplace(2)
print(inplace(3))
[1, 2, 3]
def inplace(x, lst=None):
   if lst is None: lst=[]
   lst.append()
   return lst

Еще один пример изменяемого объекта, значение которого поменялось при вызове:

def change_list(seq):
    seq[0] = 100
original = [0, 1, 2]
change_list(lst1)
original
[100, 1, 2]

Дабы не допустить изменения оригинальной последовательности, нужно передать копию изменяемого объекта:

original = [0, 1, 2]
change_list(original[:])
original
[100, 1, 2]

Указание произвольного количества аргументов

Позиционные аргументы

Иногда количество позиционных аргументов может быть переменным. Примерами таких функций могут быть max() и min(). Синтаксис для определения таких функций следующий:

def func(pos_params, *args):
    block statememt

При вызове функции нужно вводить команду следующим образом:

func(pos_params, arg1, arg2, ...)

Python обрабатывает позиционные аргументы следующим образом: подставляет обычные позиционные аргументы слева направо, а затем помещает остальные позиционные аргументы в кортеж (*args), который можно использовать в функции.

Вот так:

def add_mean(x, *data):
    return x + sum(data)/float(len(data))

add_mean(10,0,1,2,-1,0,-1,1,2)
10.5

Если лишние аргументы не указаны, значением по умолчанию будет пустой кортеж.

Произвольное количество аргументов-ключевых слов

Как и в случае с позиционными аргументами можно определять произвольное количество аргументов-ключевых слов следующим образом (в сочетании с произвольным числом необязательных аргументов из прошлого раздела):

def func(pos_params, *args, **kwargs):
    block statememt

При вызове функции нужно писать так:

func(pos_params, kw1=arg1, kw2=arg2, ...)

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

Есть функция:

def print_mean_sequences(**kwargs):
    def mean(data):
        return sum(data)/float(len(data))
    for k, v in kwargs.items():
        print k, mean(v)

print_mean_sequences(x=[1,2,3], y=[3,3,0])
y 2.0
x 2.0

Важно, что пользователь также может использовать словарь, но перед ним нужно ставить две звездочки (**):

print_mean_sequences(**{'x':[1,2,3], 'y':[3,3,0]})
y 2.0
x 2.0

Порядок вывода также не определен, потому что словарь не отсортирован.

Документирование функции

Определим функцию:

def sum(s,y): return x + y

Если изучить ее, обнаружатся два скрытых метода (которые начинаются с двух знаков нижнего подчеркивания), среди которых есть __doc__. Он нужен для настройки документации функции. Документация в Python называется docstring и может быть объединена с функцией следующим образом:

def sum(x, y):
    """Первая срока - заголовок

    Затем следует необязательная пустая строка и текст 
    документации.
    """
    return x+y

Команда docstring должна быть первой инструкцией после объявления функции. Ее потом можно будет извлекать или дополнять:

print(sum.__doc__)
sum.__doc__ += "some additional text"

Методы, функции и атрибуты, связанные с объектами функции

Если поискать доступные для функции атрибуты, то в списке окажутся следующие методы (в Python все является объектом — даже функция):

sum.func_closure   sum.func_defaults  sum.func_doc       sum.func_name
sum.func_code      sum.func_dict      sum.func_globals

И несколько скрытых методов, функций и атрибутов. Например, можно получить имя функции или модуля, в котором она определена:

>>> sum.__name__
"sum"
>>> sum.__module
"__main__"

Есть и другие. Вот те, которые не обсуждались:

sum.__call__          sum.__delattr__       sum.__getattribute__     sum.__setattr__
sum.__class__         sum.__dict__          sum.__globals__       sum.__new__           sum.__sizeof__
sum.__closure__       sum.__hash__          sum.__reduce__        sum.__str__
sum.__code__          sum.__format__        sum.__init__          sum.__reduce_ex__     sum.__subclasshook__
sum.__defaults__      sum.__get__           sum.__repr__

Рекурсивные функции

Рекурсия — это не особенность Python. Это общепринятая и часто используемая техника в Computer Science, когда функция вызывает сама себя. Самый известный пример — вычисление факториала n! = n * n — 1 * n -2 * … 2 *1. Зная, что 0! = 1, факториал можно записать следующим образом:

def factorial(n):
    if n != 0:
        return n * factorial(n-1)
    else:
        return 1

Другой распространенный пример — определение последовательности Фибоначчи:

f(0) = 1
f(1) = 1
f(n) = f(n-1) + f(n-2)

Рекурсивную функцию можно записать так:

def fibbonacci(n):
    if n >= 2:
        else:
    return 1

Важно, чтобы в ней было была конечная инструкция, иначе она никогда не закончится. Реализация вычисления факториала выше, например, не является надежной. Если указать отрицательное значение, функция будет вызывать себя бесконечно. Нужно написать так:

def factorial(n):
    assert n > 0
    if n != 0:
        return n * factorial(n-1)
    else:
        return 1

Важно!
Рекурсия позволяет писать простые и элегантные функции, но это не гарантирует эффективность и высокую скорость исполнения.

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

Глобальная переменная

Вот уже знакомый пример с глобальной переменной:

i = 0
def increment():
    global i
    i += 1

Здесь функция увеличивает на 1 значение глобальной переменной i. Это способ изменять глобальную переменную, определенную вне функции. Без него функция не будет знать, что такое переменная i. Ключевое слово global можно вводить в любом месте, но переменную разрешается использовать только после ее объявления.

За редкими исключениями глобальные переменные лучше вообще не использовать.

Присвоение функции переменной

С существующей функцией func синтаксис максимально простой:

variable = func

Переменным также можно присваивать встроенные функции. Таким образом позже есть возможность вызывать функцию другим именем. Такой подход называется непрямым вызовом функции.

Менять название переменной также разрешается:

def func(x): return x
a1 = func
a1(10)
10
a2 = a1
a2()
10

В этом примере a1, a2 и func имеют один и тот же id. Они ссылаются на один объект.

Практический пример — рефакторинг существующего кода. Например, есть функция sq, которая вычисляет квадрат значения:

def sq(x): return x*x

Позже ее можно переименовать, используя более осмысленное имя. Первый вариант — просто сменить имя. Проблема в том, что если в другом месте кода используется sq, то этот участок не будет работать. Лучше просто добавить следующее выражение:

square = sq

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

dir = 3

Теперь к ней нельзя получить доступ, а это может стать проблемой. Чтобы вернуть ее обратно, нужно просто удалить переменную:

del dir
dir()

Анонимная функция: лямбда

Лямбда-функция — это короткая однострочная функция, которой даже не нужно имя давать. Такие выражения содержат лишь одну инструкцию, поэтому, например, if, for и while использовать нельзя. Их также можно присваивать переменным:

product = lambda x,y: x*y

В отличие от функций, здесь не используется ключевое слово return. Результат работы и так возвращается.

С помощью type() можно проверить тип:

>>> type(product)
function

На практике эти функции редко используются. Это всего лишь элегантный способ записи, когда она содержит одну инструкцию.

power = lambda x=1, y=2: x**y
square = power
square(5.)
25
power = lambda x,y,pow=2: x**pow + y
[power(x,2, 3) for x in [0,1,2]]
[2, 3, 10]

Изменяемые аргументы по умолчанию

>>> def foo(x=[]):
...     x.append(1)
...     print x
...
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

Вместо этого нужно использовать значение «не указано» и заменить на изменяемый объект по умолчанию:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]

Pythonicway — Функциональное программирование в Python

Функциональным называется такой подход к процессу программирования, в программа рассматривается как вычисление математических функций, при этом не используются состояния и изменяемые объекты. Как правило, когда говорят о элементах функционального программировании в Python, то подразумеваются следующие функции: lambda, map, filter, reduce, zip.

  1. Lambda выражение в Python.
  2. Функция map() в Python.
  3. Функция filter() в Python.
  4. Функция reduce() в Python.
  5. Функция zip() в Python.

lambda оператор или lambda функция в Python это способ создать анонимную функцию, то есть функцию без имени. Такие функции можно назвать одноразовыми, они используются только при создании. Как правило, lambda функции используются в комбинации с функциями filter, map, reduce.

Синтаксис lambda выражения в Python

lambda arguments: expression

В качестве arguments передается список аргументов, разделенных запятой, после чего над переданными аргументами выполняется expression. Если присвоить lambda-функцию переменной, то получим поведение как в обычной функции (делаем мы это исключительно в целях демонстрации)

>>> multiply = lambda x,y: x * y
>>> multiply(21, 2)
42

 Но, конечно же, все преимущества lambda-выражений мы получаем, используя lambda в связке с другими функциями

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

old_list = ['1', '2', '3', '4', '5', '6', '7']

new_list = []
for item in old_list:
    new_list.append(int(item))

print (new_list)

[1, 2, 3, 4, 5, 6, 7]

Тот же эффект мы можем получить, применив функцию map:

old_list = ['1', '2', '3', '4', '5', '6', '7']
new_list = list(map(int, old_list))
print (new_list)

[1, 2, 3, 4, 5, 6, 7]

Как видите такой способ занимает меньше строк, более читабелен и выполняется быстрее. map также работает и с функциями созданными пользователем:

def miles_to_kilometers(num_miles):
    """ Converts miles to the kilometers """
    return num_miles * 1.6

mile_distances = [1.0, 6.5, 17.4, 2.4, 9]
kilometer_distances = list(map(miles_to_kilometers, mile_distances))
print (kilometer_distances)

[1.6, 10.4, 27.84, 3.84, 14.4]

А теперь то же самое, только используя lambda выражение:

mile_distances = [1.0, 6.5, 17.4, 2.4, 9]
kilometer_distances = list(map(lambda x: x * 1.6, mile_distances))

print (kilometer_distances)

[1.6, 10.4, 27.84, 3.84, 14.4]

Функция map может быть так же применена для нескольких списков, в таком случае функция-аргумент должна принимать количество аргументов, соответствующее количеству списков:

l1 = [1,2,3]
l2 = [4,5,6]

new_list = list(map(lambda x,y: x + y, l1, l2))
print (new_list)

[5, 7, 9]

Если же количество элементов в списках совпадать не будет, то выполнение закончится на минимальном списке:

l1 = [1,2,3]
l2 = [4,5]

new_list = list(map(lambda x,y:  + y, l1, l2))

print (new_list)
[5,7]

Функция filter предлагает элегантный вариант фильтрации элементов последовательности. Принимает в качестве аргументов функцию и последовательность, которую необходимо отфильтровать:

mixed = ['мак', 'просо', 'мак', 'мак', 'просо', 'мак', 'просо', 'просо', 'просо', 'мак']
zolushka = list(filter(lambda x: x == 'мак', mixed))

print (zolushka)
['мак', 'мак', 'мак', 'мак', 'мак']

Обратите внимание, что функция, передаваемая в filter должна возвращать значение True / False, чтобы элементы корректно отфильтровались.

Функция reduce принимает 2 аргумента: функцию и последовательность. reduce() последовательно применяет функцию-аргумент к элементам списка, возвращает единичное значение. Обратите внимание в Python 2.x функция reduce доступна как встроенная, в то время, как в Python 3 она была перемещена в модуль functools.

Вычисление суммы всех элементов списка при помощи reduce:

from functools import reduce
items = [1,2,3,4,5]
sum_all = reduce(lambda x,y: x + y, items)

print (sum_all)

15

Вычисление наибольшего элемента в списке при помощи reduce:

from functools import reduce
items = [1, 24, 17, 14, 9, 32, 2]
all_max = reduce(lambda a,b: a if (a > b) else b, items)

print (all_max)
32

Функция zip объединяет в кортежи элементы из последовательностей переданных в качестве аргументов.

a = [1,2,3]
b = "xyz"
c = (None, True)

res = list(zip(a, b, c))
print (res)

[(1, 'x', None), (2, 'y', True)]

Обратите внимание, что zip прекращает выполнение, как только достигнут конец самого короткого списка.

рекурсивные и лямбда-функции (анонимные функции)

В Python функцию можно вызывать саму из себя. Это называется рекурсией. В качестве примера рекурсивной функции я приведу вычисление числа в степени n (n – целое число).

def pow(x, n):
    if n == 0:
        return 1
    else:
        return x*pow(x, n-1)

И, далее, можно ее вызвать так:

Теперь подробнее разберемся как она работает. Для начала заметим, что

то есть, для вычисления значения на текущем n-м шаге достаточно взять значение на предыдущем n-1-м шаге и умножить его на x. Эта формула, по сути, отражает принцип рекурсии. В нашем случае она будет выглядеть так:

Далее, запуск функции осуществляется с аргументами 2 и 3: pow(2, 3). Она помещается в стек вызова функций, в котором хранится порядок вызова различных функций. Далее, выполняется тело функции. Проверяется первое условие. Оно оказывается ложным, так как 3 == 0 дает false. Поэтому идет переход на else и прежде чем выполнить оператор return, снова вызывается та же функция pow(2, 2).

Выполнение функции pow(2, 3) останавливается, в стек помещается вторая функция pow(2, 2) и она запускается. Снова проверяется первое условие, оно ложно, переходим по else к оператору return и опять вызываем функцию pow(2, 1).

Здесь снова все повторяется, в стек помещается очередной вызов функции и по условию вызывается следующая функция pow(2, 0).

Теперь первое условие становится истинным и функция pow(2,0) возвращает значение 1 и рекурсия не идет дальше вглубь – она останавливается. Функция pow(2.0) завершается, она удаляется из стека вызовов и управление передается функции pow(2, 1). Но она частично уже выполнена. Поэтому, берется значение 1 от pow(2, 0), результат умножается на x=2 и величина 2 возвращается функцией pow(2, 1).

Функция pow(2,1) также удаляется из стека, управление переходит к вышестоящей функции pow(2,2) и здесь мы уже имеем результат умножения x*x, то есть, 2*2 = 4. Далее, возвращаемся к самой верхней функции pow(2,3), здесь 2*4=8 и этот результат становится результатом вычисления рекурсивной функции.

Функции с произвольным числом аргументов

Для начала вспомним, что когда мы говорили о кортежах, то указывали на такую работу оператора присваивания:

Здесь x и y принимают значения 1 и 2 соответственно. Но когда этих значений было больше, чем переменных:

то возникала ошибка. Так вот, смотрите, если поставить оператор *, например, перед y, то ошибки не возникнет:

и переменная x = 1, а y = [2, 3, 4]. То есть, во вторую переменную будут записаны все оставшиеся значения в виде списка. Или же, можно сделать так:

Тогда первые три значения будут помещены в x:

x = [1, 2, 3]

а последнее в y: y = 4. То же самое работает и со списками:

и со строками:

*x, y, z = "Hello world!"

И вообще с любыми перечисляемыми типами данных. То есть, оператор * упаковывает оставшиеся значения в список. Правда, мы не можем упаковывать уже упакованные данные, например, так:

произойдет ошибка, но вот так:

будет работать.

Этот же оператор может выполнять и обратную операцию – распаковывать списки в набор данных. Смотрите, предположим, мы описываем, что счетчик в цикле for должен пробегать диапазон от -5 до 5 с шагом 1. Как вы уже знаете, это делается так:

for x in range(-5,6):
    print(x, end=" ")

Далее, мы хотим представить этот диапазон с помощью списка:

и передать его функции range. Если записать просто a:

То возникнет ошибка, т.к. функция ожидает числа, а не список. Но, записав * перед переменной a, произойдет распаковка списка в набор из двух чисел: -5 и 6:

и программа сработает без ошибок. Тогда как узнать: когда этот оператор распаковывает данные, а когда запаковывает? Очень просто:

  1. Если выполняется присвоение данных переменной с оператором *, то данные упаковываются. Например, *y, x = 1,2,3.
  2. Если выполняется передача списка с указанием оператора *, то происходит его распаковка. Например, range(*[-5,6]).

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

def myFunc(*args):
    print(args)

и вызовем ее:

myFunc()
myFunc(1)
myFunc(1, 2)
myFunc(1, 3, "hello")

Смотрите, у нас args становится кортежем с переданными значениями при вызове функции. Значит, мы спокойно можем перебрать все значения кортежа, например, в цикле for:

def myFunc(*args):
    for arg in args:
        print(arg)
 
myFunc(1, 3, "hello")

В результате получили функцию с произвольным числом аргументов. Где это может пригодиться? Например, реализовать универсальную функцию для вычисления суммы переданных элементов:

def mySum(*args):
    S = 0
    for arg in args:
        S += arg
    return S
 
print( mySum(1,2,3,4,5) )

А что если мы хотим передавать функции неограниченное количество именованных аргументов? Вот так:

myFunc(arg1=1, arg2=2, arg3=3)

В этом случае аргумент у функции следует записать с двумя звездочками:

def myFunc(**kwargs):
    print(kwargs)

И при ее вызове мы видим, что kwargs – это словарь. Как перебирать элементы словаря мы уже знаем, например, можно сделать так:

def myFunc(**kwargs):
    for name, value in kwargs.items():
        print(name, value)

и далее, выполняем определенные действия в зависимости от значений именованных аргументов.

Но, если мы теперь попытаемся вызвать функцию вот так:

myFunc(1,2,3, arg1=1, arg2=2, arg3=3)

то возникнет ошибка, т.к. первые три аргумента не именованные. Для такого варианта вызовов функцию myFunc следует записать так:

def myFunc(*args, **kwargs):
    print(args)
    print(kwargs)

Причем, вот эти неименованные аргументы должны всегда следовать перед именованными. Или же можно сделать так:

def myFunc(*args, sep="sep", end="end", **kwargs):
    print(args)
    print(kwargs)
    print(sep, end)

или так:

def myFunc(x, y, *args, sep="sep", end="end", **kwargs):
    print(args)
    print(kwargs)
    print(x, y)
    print(sep, end)

Все эти комбинации вполне допустимы, главное чтобы их порядок был именно таким: сначала фактические параметры, затем необязательный список args, затем формальные параметры и потом список этих параметров.

Анонимные или лямбда-функции

В Python существуют так называемые анонимные функции (они же лямбда-функции). Что это такое? Давайте для начала рассмотрим такой пример:

def showElements(lst, func):
    for x in lst:
        if func(x):
            print(x)
 
def __odd(x):
    return True if x%2 != 0 else False
 
a = [1,2,3,4,5,6,7]
showElements(a, __odd)

У нас имеется функция showElements, которая отображает из списка lst только те элементы, для которых функция func возвращает значение True. Далее, мы создаем вспомогательную функцию __odd, которая возвращает True для нечетных значений. И идет вызов showElements для списка a и селектора в виде функции __odd.

Но что если мы захотим изменить селектор и выбирать, например, все четные значения? Нужно создавать новую функцию и затем указывать ссылку на нее? Это как то не очень удобно. Вот здесь нам на помощь приходят лямбда-функции. Их можно объявить в любом месте программы по следующему синтаксису:

lambda arg1, arg2, …: выражение

Например, так:

и, затем, вызвать ее:

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

В нашем случае мы можем записать такую функцию сразу в качестве второго аргумента:

showElements(a, lambda x: True if x%2==0 else False)

Видите, как это удобно, понятно и наглядно. Мы сразу видим как будет выбирать значения функция showElements.

Если анонимная функция не принимает никаких аргументов, то она записывается так:

p = lambda : "hello world"
p()

Вот такие интересные и полезные возможности в объявлении функций существуют в языке Python.

Задания для самоподготовки

1. Написать рекурсивную функцию для вычисления факториала числа n:

2. Написать функцию для вычисления среднего арифметического переданных ей значений в виде аргументов:

arg1, arg2, …, argN

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

Изучаем lambda-функции в Python

Оператор lambda это анонимная, или несвязанная функция, при этом довольно ограниченная. Давайте взглянем на несколько базовых примеров, и взглянем, можем ли мы найти применение данной функции. Обычно в таких примерах показывают унылые операции с дублированием. Чтобы сделать обучение интереснее, в нашем примере мы рассмотрим, как найти квадратный корень используя модуль math. Для начала, мы покажем обычную функцию, потом аналогичный с лямбдой-функцией:

import math def sqroot(x): «»» Находим квадратный корень. «»» return math.sqrt(x) square_rt = lambda x: math.sqrt(x)

import math

 

def sqroot(x):

    «»»

    Находим квадратный корень.

    «»»

    return math.sqrt(x)

 

square_rt = lambda x: math.sqrt(x)

Если вы используете каждую из этих функцию, вы закончите с запятой. Вот еще несколько примеров:

print(sqroot(49)) # 7.0 print(square_rt(64)) # 8.0

print(sqroot(49)) # 7.0

print(square_rt(64)) # 8.0

Довольно прозрачно. Но где найти применение лямбде в реальной жизни? Может в программе калькуляторе? Это будет работать, но это будет достаточно ограниченным приложением как для Python. Основную часть возможностей Python, которые демонстрирует лямбда можно увидеть в обратных вызовах Tkinter. Tkinter – это включенный в Python набор инструментов, для создания графических интерфейсов.

Tkinter + lambda

Мы начнем с Tkinter, так как он включен в стандартный пакет Python. Рассмотрим достаточно простой скрипт с тремя кнопками, две из которых связаны с обработчиком событий с использованием лямбды:

import Tkinter as tk class App: «»»»»» def __init__(self, parent): «»»Конструктор»»» frame = tk.Frame(parent) frame.pack() btn22 = tk.Button( frame, text=»22″, command=lambda: self.printNum(22) ) btn22.pack(side=tk.LEFT) btn44 = tk.Button( frame, text=»44″, command=lambda: self.printNum(44) ) btn44.pack(side=tk.LEFT) quitBtn = tk.Button(frame, text=»QUIT», fg=»red», command=frame.quit) quitBtn.pack(side=tk.LEFT) def printNum(self, num): print(«Вы нажали кнопку: %s» % num) if __name__ == «__main__»: root = tk.Tk() app = App(root) root.mainloop()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

import Tkinter as tk

 

class App:

    «»»»»»

    def __init__(self, parent):

        «»»Конструктор»»»

        frame = tk.Frame(parent)

        frame.pack()

    

        btn22 = tk.Button(

            frame,

            text=»22″,

            command=lambda: self.printNum(22)

        )

        btn22.pack(side=tk.LEFT)

 

        btn44 = tk.Button(

            frame,

            text=»44″,

            command=lambda: self.printNum(44)

        )

        btn44.pack(side=tk.LEFT)

    

        quitBtn = tk.Button(frame, text=»QUIT», fg=»red», command=frame.quit)

        quitBtn.pack(side=tk.LEFT)

 

    def printNum(self, num):

        print(«Вы нажали кнопку: %s» % num)

 

 

if __name__ == «__main__»:

    root = tk.Tk()

    app = App(root)

    root.mainloop()

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Обратите внимание на переменные btn22 и btn44. Именно здесь происходят события. Мы создали экземпляр tk.Button и связываемся с нашим методом printNum одним махом. Наша лямбда присваивается параметру команды кнопки. Это значит, что мы создаем одноразовую функцию для команды, по аналогии с кнопкой выхода, где мы вызываем метод выхода из фрейма. Разница в том, что отдельная лямбда – это метод, который вызывает другой метод и передает ему целое число. В методе printNum, мы пишем  в stdout о том, какая кнопка была нажата, пользуясь информацией, которая была передана функцией lambda. Улавливаете? Если да, то мы продолжим. Если нет – перечитайте данный параграф столько раз, сколько нужно для того, чтобы эта информация усвоилась, или пока не сойдете с ума, в любом случае, что-то должно произойти первым.

Подведем итоги

Оператор lambda, в том числе, используется во всех других проектах и операциях. Если вы загуглите фразу «Python lambda«, вам выдаст великое множество различных кодов. Например, если вы поищете «Django lambda», вы заметите, что в Django содержит набор моделей, которые используют лямбду. Плагин Elixir для SqlAlchemy также использует лямбду. Если вы будете обращать на это внимание, как часто вы будете натыкаться на этот маленький создатель функций.

Python лямбда — анонимная функция

  • Лямбда-функция Python или анонимная функция Python не имеют имени.
  • Мы можем определить анонимную функцию, используя зарезервированное ключевое слово lambda .
  • Область анонимной функции ограничена текущей областью , где она определена.
  • Лямбда-функция может иметь один или несколько аргументов, но может иметь только одно выражение .
  • Выражение вычисляется, и результат возвращается из лямбда-функции.
  • Лямбда-функции обычно используются с операциями map (), filter () и reduce ().

Синтаксис лямбда-функции Python

Синтаксис лямбда-функции:

лямбда-аргументы: выражение
 

Пример анонимной функции Python

Допустим, у нас есть функция для получения площади прямоугольника.

def area_of_rectangle (l, w):
    вернуть l * w


print (f'Площадь прямоугольника (4, 5) равна {area_of_rectangle (4, 5)} ')
 

Давайте создадим анонимную функцию, используя ключевое слово lambda, чтобы получить площадь прямоугольника.

rectangle_area = лямбда x, y: x * y

print (f'Area of ​​Rectangle (4, 5) равна {rectangle_area (4, 5)} ')
 

Когда использовать анонимную функцию?

  • Для небольших тривиальных задач небольшой сложности.
  • Когда функция имеет только одно выражение.
  • Для повторяющихся задач, носящих временный характер.
  • Если вы хотите, чтобы область действия функции была ограничена только текущей областью.
  • Это полезно, когда аргументом функции является другая функция, такая как функции map (), filter () и reduce ().

Лямбда-функция с картой ()

Функция map () принимает в качестве аргументов функцию и итерацию. Функция применяется к каждому элементу в итерируемом объекте, и возвращается обновленный итеративный объект.

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

list_numbers = [1, 2, 3, 4]

list_numbers = map (лямбда x: x * 10, list_numbers)

для числа в list_numbers:
    print (число, конец = "")
 

Выход:

Лямбда-функция Python с map ()

Лямбда-функция с фильтром ()

Встроенная функция filter () принимает в качестве аргумента функцию и итерацию.Функция применяется к каждому элементу итерации. Если функция возвращает True, элемент добавляется к возвращаемой итерации.

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

list_numbers = [1, 2, 3, 4, 5, 6]

list_numbers = filter (лямбда x: x% 2 == 0, list_numbers)

для числа в list_numbers:
    print (число, конец = "")
 
Лямбда-функция Python с filter ()

Лямбда-функция с функцией reduce ()

Функция reduce () присутствует в модуле functools .Эта функция принимает в качестве аргумента функцию и последовательность. Функция должна принимать два аргумента. Элементы из последовательности передаются в функцию вместе с накопленным значением. Конечный результат — одно значение.

Допустим, у нас есть список целых чисел, и мы хотим получить сумму всех его элементов. Здесь мы можем использовать функцию reduce () с лямбда-функцией.

из functools import уменьшить

list_ints = [1, 2, 3, 4, 5, 6]

total = reduce (лямбда x, y: x + y, list_ints)

print (f 'Сумма элементов list_ints равна {total}')
 
Лямбда-функция Python с функцией reduce ()

Лямбда-функция Python без аргументов

Кто-то спросил меня, можем ли мы иметь лямбда-функцию без аргументов?

Да, мы можем определить лямбда-функцию без аргументов.Но бесполезно, потому что оперировать будет не на чем. Давайте посмотрим на простой пример.

get_5 = лямбда: 5

печать (get_5 ()) # 5
 

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


Заключение

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


Артикул:

.

Python Lambda (анонимная) Функция

Что такое лямбда-функции в Python?

В Python анонимная функция — это функция, которая определяется без имени.

В то время как обычные функции определяются с помощью ключевого слова def в Python, анонимные функции определяются с помощью ключевого слова lambda .

Следовательно, анонимные функции также называются лямбда-функциями.


Как использовать лямбда-функции в Python?

Лямбда-функция в Python имеет следующий синтаксис.

Синтаксис лямбда-функции в python

лямбда-аргументы: выражение 

Лямбда-функции могут иметь любое количество аргументов, но только одно выражение. Выражение оценивается и возвращается. Лямбда-функции можно использовать везде, где требуются функциональные объекты.


Пример лямбда-функции в python

Вот пример лямбда-функции, которая удваивает входное значение.

  # Программа для демонстрации использования лямбда-функций
double = лямбда x: x * 2

печать (двойная (5))  

Выход

  10  

В приведенной выше программе лямбда x: x * 2 — это лямбда-функция.Здесь x — это аргумент, а x * 2 — это выражение, которое вычисляется и возвращается.

У этой функции нет имени. Он возвращает функциональный объект, которому присвоен идентификатор double . Теперь мы можем вызывать это как обычную функцию. Выписка

double = лямбда x: x * 2 

почти то же самое, что:

def double (x):
   возврат x * 2 

Использование лямбда-функции в Python

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

В Python мы обычно используем его в качестве аргумента функции высшего порядка (функции, которая принимает другие функции в качестве аргументов). Лямбда-функции используются вместе со встроенными функциями, такими как filter () , map () и т. Д.

Пример использования с filter ()

Функция filter () в Python принимает в качестве аргументов функцию и список.

Функция вызывается со всеми элементами в списке, и возвращается новый список, содержащий элементы, для которых функция оценивает значение True .

Вот пример использования функции filter () для фильтрации только четных чисел из списка.

  # Программа для фильтрации только четных элементов из списка
my_list = [1, 5, 4, 6, 8, 11, 3, 12]

new_list = список (фильтр (лямбда x: (x% 2 == 0), my_list))

print (new_list)  

Выход

  [4, 6, 8, 12]  

Пример использования с map ()

Функция map () в Python принимает функцию и список.

Функция вызывается со всеми элементами в списке, и возвращается новый список, содержащий элементы, возвращаемые этой функцией для каждого элемента.

Вот пример использования функции map () для удвоения всех элементов в списке.

  # Программа для удвоения каждого элемента в списке с помощью map ()

my_list = [1, 5, 4, 6, 8, 11, 3, 12]

new_list = список (карта (лямбда x: x * 2, my_list))

print (new_list)  

Выход

  [2, 10, 8, 12, 16, 22, 6, 24]  
.

Анонимная функция Python — JournalDev

Добро пожаловать в учебник по анонимной функции Python. В предыдущем уроке мы узнали о Python Recursion.

Анонимная функция Python

Анонимная функция Python — это функция, у которой нет имени. Следовательно, мы можем использовать функцию Python Anonymous для небольшого объема программы. Обычно мы определяем функцию Python с помощью ключевого слова def . Но мы определяем анонимную функцию с помощью ключевого слова lambda . Базовая структура анонимной функции приведена ниже.

 
лямбда-аргументы: выражение
  

Посмотрите внимательно, что, принимая один или несколько аргументов , анонимная функция имеет только одно выражение . Итак, если мы хотим создать функцию, которая будет вычислять сумму двух чисел. Следующий код сделает это;

 
def sum (a, b):
        вернуть a + b

печать (сумма (1, 2))
печать (сумма (3, 5))
  

Но мы можем преобразовать эту функцию в анонимную функцию. Код будет таким

 
сумма = лямбда a, b: (a + b)

печать (сумма (1,2))
печать (сумма (3,5))
  

Почему мы должны использовать анонимную функцию Python

Может показаться, что мы можем заменить анонимную функцию обычной функцией.Тогда почему мы должны использовать анонимную функцию? Во-первых, вам может потребоваться многократно выполнять одну задачу в пределах вашей области действия. Следовательно, для этого вам понадобится временная функция. В этом вам может помочь лямбда / анонимная функция. Потому что анонимная функция действительна между областями видимости, в то время как обычная функция действительна в программе.

Выражение или утверждение

Основная путаница при реализации анонимной функции заключается в отсутствии возможности различать выражение и утверждение.По сути, оператор ничего не возвращает, а выражение дает хотя бы одно значение. Простые математические выражения, такие как сложение, умножение, деление, являются выражениями и могут использоваться в лямбда / анонимных функциях. Итак, вам нужно добавить выражение, чтобы результат выражения мог быть возвращен с помощью лямбда / анонимной функции.

Некоторое использование лямбда / анонимной функции

Теперь мы собираемся увидеть некоторые общие примеры использования лямбда. Используя функцию map () и filter () , мы можем изменить список с помощью анонимной функции.Например, мы хотим увеличить все числа в списке на n. Для этого код должен быть таким:

 
#initial list
l = [1,2,3,4,5,6,7,8]

# распечатать исходный список
print ("Первоначальный список:")
печать (л)

# выбрать n
n = int (input ('Введите значение n:'))

# увеличиваем все значения списка, используя карту с помощью лямбда
l = список (карта (лямбда x: x + n, l))

# распечатать измененный список
print ("Измененный список:")
печать (л)
  

Результатом будет

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

 
#initialize list1
list1 = [1,2,3,4,5,6,7,8]

#print list1
print ("Список1:", конец = '')
печать (список1)

#intialize list2 для выбранных номеров
list2 = [2,3,5,9,12,14]

#print list2
print ("Список2:", конец = '')
печать (список2)

'' '
сравните с использованием лямбда-функции, если значение находится в списке2, если да, то сохраните результат и назначьте его в список3
'' '
список3 = список (фильтр (лямбда x: x в списке2, список1))

# распечатать измененный список
print "List3 (List1 пересекает List2):", end = '')
печать (список3)

  

Результатом вышеприведенной программы будет

Итак, это все об анонимной функции Python.Надеюсь, что теперь вам понятна анонимная функция Python. Для дальнейшего запроса используйте поле для комментариев. Удачи!

.

Анонимная функция Python (лямбда)

В этом руководстве мы обсудим анонимных функций в Python . В Python анонимная функция также известна как лямбда-функция .

Содержание

Анонимная функция Python (лямбда)

Анонимная функция в Python — это функция без имени.

Функция в Python определяется с помощью ключевого слова def . В Python анонимная / лямбда-функция определяется с помощью ключевого слова lambda .

Синтаксис анонимной функции в python

В Python лямбда-функция имеет следующий синтаксис:

 лямбда <аргументы>: выражение 

Анонимная функция допускает нескольких аргументов , но только одно выражение , выражение вычисляется на основе переданных аргументов и возвращается результат выражения.

Пример лямбда-функции Python

В следующем примере мы используем лямбда-функцию, которая возвращает квадрат заданного числа .

 my_square = лямбда число: число * число

п = 4

# Вывод: Квадрат числа 4 равен: 16
print ("Квадрат числа", n, "is:", my_square (n)) 

Выход:

В приведенном выше примере lambda num: num * num — это лямбда-функция, которая возвращает квадрат заданного аргумента. Здесь число — аргумент, а число * число — выражение.

У лямбда-функции нет имени, результат лямбда-функции присваивается идентификатору my_square .

Лямбда-функция lambda num: num * num эквивалентна следующей пользовательской функции:

 def my_square (число):
   return num * num 

Пример filter () с лямбда-функцией

Функция filter () принимает два аргумента: функцию и список.

Функция filter () возвращает новый список со всеми теми элементами входного списка, которые удовлетворяют условию функции, или, другими словами, filter () возвращает те элементы, для которых функция оценивает значение true.

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

 # Программа для фильтрации нечетных чисел из заданного списка

lis = [10, 3, 2, 11, 13, 14, 15]

lis_new = список (фильтр (лямбда число: (число% 2! = 0), список))

# Вывод: [3, 11, 13, 15]
печать (lis_new) 

Выход:

Пример map () с лямбда-функцией

Подобно функции filter (), функция map () принимает функцию и список в качестве аргументов.

Функция map () возвращает новый список с элементами, которые возвращаются функцией для каждого из элементов входного списка .

Здесь мы используем map () и лямбда-функцию для возврата квадрата каждого элемента данного списка.

 # Программа для определения квадрата каждого элемента списка

lis = [10, 9, 1, 2, 7, 11]

lis_new = список (карта (лямбда число: число * число, список))

# Вывод: [100, 81, 1, 4, 49, 121]
печать (lis_new) 

Вывод:

Как видно из вывода, в списке есть квадрат каждого элемента входного списка.

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *