Python 3.8: что нового и как этим пользоваться?

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

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


Python

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

print( add(1, 2) ) # 3

1 2 3 4

defadd(a,b)

returna+b

print(add(1,2))# 3

Каждая функция выдает определенный результат. Если вы не указываете на выдачу конкретного результата, она, тем не менее, выдаст результат None (ничего). В нашем примере мы указали выдать результат a + b. Как вы видите, мы можем вызвать функцию путем передачи двух значений. Если вы передали недостаточно, или слишком много аргументов для данной функции, вы получите ошибку:

Python

add(1)

Traceback (most recent call last): File «<string>», line 1, in <fragment> TypeError: add() takes exactly 2 arguments (1 given)

1 2 3 4 5

add(1)

Traceback(most recent call last)

File»<string>»,line1,in<fragment>

TypeErroradd()takes exactly2arguments(1given)

Вы также можете вызвать функцию, указав наименование аргументов:

Python

print( add(a = 2, b = 3) ) # 5

total = add(b = 4, a = 5) print(total) # 9

1 2 3 4

print(add(a=2,b=3))# 5

total=add(b=4,a=5)

print(total)# 9

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

Это стандартный путь вызова функции в случае, если вы хотите дальше использовать её результат.

Вы, возможно, подумаете: «А что, собственно, произойдет, если мы укажем аргументы, но они названы неправильно? Это сработает?» Давайте попробуем на примере:

Python

add(c=5, d=2)

Traceback (most recent call last): File «<string>», line 1, in <fragment> TypeError: add() got an unexpected keyword argument ‘c’

1 2 3 4 5

add(c=5,d=2)

Traceback(most recent call last)

File»<string>»,line1,in<fragment>

TypeErroradd()got an unexpected keywordargument’c’

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

Функции как объекты

Создавая объект функции оператором , как было показано в листинге 1, можно привязать созданный функциональный объект к имени в точности так же, как можно было бы привязать к этому имени число или строку . Этот пример подтверждает статус функций как объектов первого класса в Python. Функция в Python — это всего лишь ещё одно значение, с которым можно что-то сделать.

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

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

Комбинируя эти три функции, можно реализовать неожиданно широкий диапазон операций потока управления, не прибегая к императивным утверждениям, а используя лишь выражения в функциональном стиле, как показано в листинге 2 (файл funcH.py из архива python_functional.tgz в разделе «Материалы для скачивания»):

Листинг 2. Функции высших порядков Python
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
def input_arg():
    global arg
    arg = ( lambda: ( len( sys.argv ) > 1 and int( sys.argv ) ) or \
                      int( input( "число?: " ) ) )()
    return arg

print( 'аргумент = {}'.format( input_arg() ) )
print( list( map( lambda x: x + 1, range( arg ) ) ) )
print( list( filter( lambda x: x > 4, range( arg ) ) ) )

import functools
print( '{}! = {}'.format( arg, functools.reduce( lambda x, y: x * y,
                                                 range( 1, arg ) ) ) )

Примечание. Этот код несколько усложнён по сравнению с предыдущим примером из-за следующих аспектов, связанных с совместимостью Python версий 2 и 3:

  • Функция , объявленная как встроенная в Python 2, в Python 3 была вынесена в модуль и её прямой вызов по имени вызовет исключение , поэтому для корректной работы вызов должен быть оформлен как в примере или включать строку:
  • Функции и в Python 3 возвращают не список (что уже показывалось при обсуждении различий версий), а объекты-итераторы вида:

    <map object at 0xb7462bec>
    <filter object at 0xb75421ac>

Для получения всего списка значений для них вызывается функция .

Поэтому такой код сможет работать в обеих версиях Python:

$ python3 funcH.py 7
аргумент = 7


7! = 720

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

What is a function in Python?

In Python, a function is a group of related statements that performs a specific task.

Functions help break our program into smaller and modular chunks. As our program grows larger and larger, functions make it more organized and manageable.

Furthermore, it avoids repetition and makes the code reusable.

Syntax of Function

def function_name(parameters):
	"""docstring"""
	statement(s)

Above shown is a function definition that consists of the following components.

  1. Keyword that marks the start of the function header.
  2. A function name to uniquely identify the function. Function naming follows the same .
  3. Parameters (arguments) through which we pass values to a function. They are optional.
  4. A colon (:) to mark the end of the function header.
  5. Optional documentation string (docstring) to describe what the function does.
  6. One or more valid python statements that make up the function body. Statements must have the same indentation level (usually 4 spaces).
  7. An optional statement to return a value from the function.

How to call a function in python?

Once we have defined a function, we can call it from another function, program or even the Python prompt. To call a function we simply type the function name with appropriate parameters.

Note: Try running the above code in the Python program with the function definition to see the output.

Функция xrange() в Python 2

Использование довольно популярно в Python 2.x ввиду создания итерируемого объекта, то есть цикла for или включения в виде , множества или словаря. Поведение напоминало работу генератора, то есть «ленивое вычисление», однако здесь итерация xrange не является исчерпывающей, то есть вы можете перебирать ее бесконечно.


Благодаря «ленивому вычислению», преимущество обычного в том, что обычно быстрее, если вы итерировали только раз (в цикле ). Однако по сравнению с одноразовыми итерациями, не рекомендуется повторять итерацию множество раз, так как каждый раз итерация начинается с нуля.

В Python 3 была имплементирована вместо . Функция больше использоваться не может, вызывая в Python 3 ошибку .

Python

import timeit

n = 10000 def test_range(n): return for i in range(n): pass

def test_xrange(n): for i in xrange(n): pass

1 2 3 4 5 6 7 8 9 10

importtimeit

n=10000

deftest_range(n)

returnforiinrange(n)

pass

deftest_xrange(n)

foriinxrange(n)

pass

Python 2

Python

print ‘Python’, python_version()

print ‘\ntiming range()’ %timeit test_range(n)

print ‘\n\ntiming xrange()’ %timeit test_xrange(n)

1 2 3 4 5 6 7 8

print’Python’,python_version()

print’\ntiming range()’

%timeittest_range(n)

print’\n\ntiming xrange()’

%timeittest_xrange(n)

Shell

Python 2.7.6

timing range() 1000 loops, best of 3: 433 µs per loop

timing xrange() 1000 loops, best of 3: 350 µs per loop

1 2 3 4 5 6 7 8

Python2.7.6

timing range()

1000loops,best of3433µsper loop

timing xrange()

1000loops,best of3350µsper loop

Python 3

Python

print(‘Python’, python_version())

print(‘\ntiming range()’) %timeit test_range(n)

1 2 3 4

print(‘Python’,python_version())

print(‘\ntiming range()’)

%timeittest_range(n)

Shell

Python 3.8.1

timing range() 1000 loops, best of 3: 520 µs per loop

1 2 3 4

Python3.8.1


timing range()

1000loops,best of3520µsper loop

Python

print(xrange(10))

1 print(xrange(10))

Shell

————————————————————————— NameError Traceback (most recent call last)

<ipython-input-5-5d8f9b79ea70> in <module>() —-> 1 print(xrange(10))

NameError: name ‘xrange’ is not defined

1 2 3 4 5 6 7 8

—————————————————————————

NameError                                 Traceback(most recent call last)

<ipython-input-5-5d8f9b79ea70>in<module>()

—->1print(xrange(10))

NameErrorname’xrange’isnotdefined

Функции в Python

Функции в Python определяются 2-мя способами: через определение или через анонимное описание . Оба этих способа определения доступны, в той или иной степени, и в некоторых других языках программирования. Особенностью Python является то, что функция является таким же именованным объектом, как и любой другой объект некоторого типа данных, скажем, как целочисленная переменная. В листинге 1 представлен простейший пример (файл func.py из архива python_functional.tgz в разделе «Материалы для скачивания»):

Листинг 1. Определения функций
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys

def show( fun, arg ):
    print( '{} : {}'.format( type( fun ), fun ) )
    print( 'arg={} => fun( arg )={}'.format( arg, fun( arg ) ) )

if len( sys.argv ) > 1: n = float( sys.argv )
else: n = float( input( "число?: " ) )

def pow3( n ):                     # 1-е определение функции
    return n * n * n
show( pow3, n )

pow3 = lambda n: n * n * n         # 2-е определение функции с тем же именем
show( pow3, n )

show( ( lambda n: n * n * n ), n ) # 3-е, использование анонимного описание функции

При вызове всех трёх объектов-функций мы получим один и тот же результат:

$ python func.py 1.3
<type 'function'> : <function pow3 at 0xb7662844>
arg=1.3 => fun( arg )=2.197
<type 'function'> : <function <lambda> at 0xb7662bc4>
arg=1.3 => fun( arg )=2.197
<type 'function'> : <function <lambda> at 0xb7662844>
arg=1.3 => fun( arg )=2.197

Ещё более отчётливо это проявляется в Python версии 3, в которой всё является классами (в том числе, и целочисленная переменная), а функции являются объектами программы, принадлежащими к классу :

$ python3 func.py 1.3
<class 'function'> : <function pow3 at 0xb74542ac>
arg=1.3 => fun( arg )=2.1970000000000005
<class 'function'> : <function <lambda> at 0xb745432c>
arg=1.3 => fun( arg )=2.1970000000000005
<class 'function'> : <function <lambda> at 0xb74542ec>
arg=1.3 => fun( arg )=2.1970000000000005

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

Если функциональные объекты Python являются такими же объектами, как и другие объекты данных, значит, с ними можно и делать всё то, что можно делать с любыми данными:

  • динамически изменять в ходе выполнения;
  • встраивать в более сложные структуры данных (коллекции);
  • передавать в качестве параметров и возвращаемых значений и т.д.

На этом (манипуляции с функциональными объектами как с объектами данных) и базируется функциональное программирование. Python, конечно, не является настоящим языком функционального программирования, так, для полностью функционального программирования существуют специальные языки: Lisp, Planner, а из более свежих: Scala, Haskell. Ocaml, … Но в Python можно «встраивать» приёмы функционального программирования в общий поток императивного (командного) кода, например, использовать методы, заимствованные из полноценных функциональных языков. Т.е. «сворачивать» отдельные фрагменты императивного кода (иногда достаточно большого объёма) в функциональные выражения.

Временами спрашивают: «В чём преимущества функционального стиля написания отдельных фрагментов для программиста?». Основным преимуществом функционального программирования является то, что после однократной отладки такого фрагмента в нём при последующем многократном использовании не возникнут ошибки за счёт побочных эффектов, связанных с присвоениями и конфликтом имён.

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

print (  )

В результате запуска получаем:

$ python funcp.py

Область видимость и глобальные переменные

Концепт области (scope) в Пайтон такой же, как и в большей части языков программирования. Область видимости указывает нам, когда и где переменная может быть использована. Если мы определяем переменные внутри функции, эти переменные могут быть использованы только внутри это функции. Когда функция заканчиваются, их можно больше не использовать, так как они находятся вне области видимости. Давайте взглянем на пример:

Python

def function_a(): a = 1 b = 2 return a+b

def function_b(): c = 3 return a+c

print( function_a() ) print( function_b() )

1 2 3 4 5 6 7 8 9 10 11 12

deffunction_a()

a=1

b=2

returna+b

deffunction_b()

c=3

returna+c

print(function_a())

print(function_b())

Если вы запустите этот код, вы получите ошибку:

Python

NameError: global name ‘a’ is not defined

1 NameErrorglobalname’a’isnotdefined

Это вызвано тем, что переменная определенна только внутри первой функции, но не во второй. Вы можете обойти этот момент, указав в Пайтоне, что переменная а – глобальная (global). Давайте взглянем на то, как это работает:

Python

def function_a(): global a a = 1 b = 2 return a+b

def function_b(): c = 3 return a+c

print( function_a() ) print( function_b() )

1 2 3 4 5 6 7 8 9 10 11 12 13

deffunction_a()

globala

a=1

b=2

returna+b

deffunction_b()

c=3

returna+c

print(function_a())

print(function_b())

Этот код работает, так как мы указали Пайтону сделать а – глобальной переменной, а это значит, что она работает где-либо в программе. Из этого вытекает, что это настолько же хорошая идея, насколько и плохая. Причина, по которой эта идея – плохая в том, что нам становится трудно сказать, когда и где переменная была определена. Другая проблема заключается в следующем: когда мы определяем «а» как глобальную в одном месте, мы можем случайно переопределить её значение в другом, что может вызвать логическую ошибку, которую не просто исправить.

Функции

Последнее обновление: 11.04.2018

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

def имя_функции ():
    инструкции

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

Например, определение простейшей функции:

def say_hello():
    print("Hello")

Функция называется . Она не имеет параметров и содержит одну единственную инструкцию, которая выводит на консоль строку «Hello».

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

def say_hello():
    print("Hello")
    
say_hello()
say_hello()
say_hello()

Здесь три раза подряд вызывается функция say_hello. В итоге мы получим следующий консольный вывод:

Hello
Hello
Hello

Теперь определим и используем функцию с параметрами:

def say_hello(name):
    print("Hello,",name)

say_hello("Tom")
say_hello("Bob")
say_hello("Alice")

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

Hello, Tom
Hello, Bob
Hello, Alice

Значения по умолчанию

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

def say_hello(name="Tom"):
    print("Hello,", name)
	
say_hello()
say_hello("Bob")

Здесь параметр name является необязательным. И если мы не передаем при вызове функции для него значение, то применяется значение по умолчанию, то есть строка «Tom».

Именованные параметры

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

def display_info(name, age):
    print("Name:", name, "\t", "Age:", age)
	
display_info("Tom", 22)

При вызове функции первое значение «Tom» передается первому параметру — параметру name, второе значение — число 22 передается второму параметру — age. И так далее по порядку. Использование именованных параметров позволяет переопределить порядок передачи:

def display_info(name, age):
    print("Name:", name, "\t", "Age:", age)
	
display_info(age=22, name="Tom")

Именованные параметры предполагают указание имени параметра с присвоением ему значения при вызове функции.

Неопределенное количество параметров

С помощью символа звездочки можно определить неопределенное количество параметров:

def sum(*params):
    result = 0
    for n in params:
        result += n
    return result


sumOfNumbers1 = sum(1, 2, 3, 4, 5)		# 15
sumOfNumbers2 = sum(3, 4, 5, 6)			# 18
print(sumOfNumbers1)
print(sumOfNumbers2)

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

Возвращение результата

Функция может возвращать результат. Для этого в функции используется оператор return, после которого указывается возвращаемое значение:

def exchange(usd_rate, money):
    result = round(money/usd_rate, 2)
    return result

result1 = exchange(60, 30000)
print(result1)
result2 = exchange(56, 30000)
print(result2)
result3 = exchange(65, 30000)
print(result3)

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

В Python функция может возвращать сразу несколько значений:

def create_default_user():
    name = "Tom"
    age = 33
    return name, age


user_name, user_age = create_default_user()
print("Name:", user_name, "\t Age:", user_age)

Здесь функция create_default_user возвращает два значения: name и age. При вызове функции эти значения по порядку присваиваются переменным user_name и user_age, и мы их можем использовать.

Функция main

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

def main():
    say_hello("Tom")
    usd_rate = 56
    money = 30000
    result = exchange(usd_rate, money)
    print("К выдаче", result, "долларов")


def say_hello(name):
    print("Hello,", name)
    
    
def exchange(usd_rate, money):
    result = round(money/usd_rate, 2)
    return result

# Вызов функции main
main()

НазадВперед

Docstrings

The first string after the function header is called the docstring and is short for documentation string. It is briefly used to explain what a function does.

Although optional, documentation is a good programming practice. Unless you can remember what you had for dinner last week, always document your code.

In the above example, we have a docstring immediately below the function header. We generally use triple quotes so that docstring can extend up to multiple lines. This string is available to us as the attribute of the function.

For example:

Try running the following into the Python shell to see the output.

To learn more about docstrings in Python, visit Python Docstrings.

Методы списков

len()

Метод возвращает длину объекта (списка, строки, кортежа или словаря).

принимает один аргумент, который может быть или последовательностью (например, строка, байты, кортеж, список, диапазон), или коллекцией (например, словарь, множество, frozenset).

list1 =   # список
print(len(list1)) # в списке 3 элемента, в выводе команды будет "3"

str1 = 'basketball'  # строка
print(len(str1))  # в строке 9 букв, в выводе команды будет "9"

tuple1 = (2, 3, 4, 5)  # кортеж
print(len(tuple1))  # в кортеже 4 элемента, в выводе команды будет "4"

dict1 = {'name': 'John', 'age': 4, 'score': 45} # словарь
print(len(dict1))  # в словаре 3 пары ключ-значение, в выводе команды будет "3"

index()

возвращает индекс элемента. Сам элемент передается методу в качестве аргумента. Возвращается индекс первого вхождения этого элемента (т. е., если в списке два одинаковых элемента, вернется индекс первого).

numbers = 
words = 

print(numbers.index(9)) # 4
print(numbers.index(2)) # 1
print(words.index("I")) # 0
print(words.index("JavaScript")) # возвращает ValueError, поскольку 'JavaScript' в списке 'words' нет

Первый результат очевиден. Второй и третий output демонстрируют возврат индекса именно первого вхождения.

Цифра «2» встречается в списке дважды, первое ее вхождение имеет индекс 1, второе — 2. Метод index() возвращает индекс 1.

Аналогично возвращается индекс 0 для элемента «I».

Если элемент, переданный в качестве аргумента, вообще не встречается в списке, вернется ValueError. Так получилось с попыткой выяснить индекс «JavaScript» в списке .

Опциональные аргументы

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

words = 
print(words.index("am", 2, 5)) # 4

Метод index() будет искать элемент «am» в диапазоне от элемента с индексом 2 (включительно) до элемента с индексом 5 (этот последний элемент не входит в диапазон).

При этом возвращаемый индекс — индекс элемента в целом списке, а не в указанном диапазоне.

pop()

Метод удаляет и возвращает последний элемент списка.

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

Если в списке нет указанного вами индекса, метод выбросит exception .

cities = 

print "City popped is: ", cities.pop() # City popped is: San Francisco
print "City at index 2 is  : ", cities.pop(2) # City at index 2 is: San Antonio

Базовый функционал стека

Для реализации базового функционала стека в программах на Python часто используется связка метода pop() и метода append():

stack = []

for i in range(5):
    stack.append(i)

while len(stack):
    print(stack.pop())

С этим читают