Добавил:
Developer Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лекции / 7. Функции - Jupyter Notebook

.pdf
Скачиваний:
42
Добавлен:
15.12.2022
Размер:
800 Кб
Скачать

15.10.2022, 11:11

7. Функции - Jupyter Notebook

In [33]:

1 def hello_i18n(name):

2if lang == 'ru':

3print("Привет,",name)

4else:

5

print("Hello,",name)

6

 

7

lang = 'ru'

8

print("Hello world")

9

hello_i18n('Ivan')

10

11lang = 'en'

12hello_i18n('John')

Hello world

Привет, Ivan Hello, John

Как видите, сейчс поведение функции зависит от того, чему равняется переменная lang , определенная вне функции. Может быть и в функции factorial() можно было обратиться к переменной f до того момента, как мы положили в неё число 1? Давайте попробуем:

In [34]:

1 def factorial(n):

2print("In the function, before assignment, f =", f)

3f = 1

4for i in range(2, n+1):

5f = f * i

6 print("In the function, f =", f)

7return f

In [35]:

1 factorial(2)

---------------------------------------------------------------------------

UnboundLocalError

Traceback (most recent call last)

<ipython-input-35-26972ebb8a51> in <module>

----> 1

factorial(2)

 

<ipython-input-34-9edfcfd8c667> in factorial(n)

1

def factorial(n):

 

----> 2

print("In the function, before assignment, f =", f)

3f = 1

4for i in range(2, n+1):

5f = f * i

UnboundLocalError: local variable 'f' referenced before assignment

В этом случае Python выдаёт ошибку: локальная переменная f использовалась до присвоения значения. В чём разница между этим кодом и предыдущим?

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/7. Функции.ipynb

11/17

15.10.2022, 11:11

7. Функции - Jupyter Notebook

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

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

In [36]:

1

def set_lang():

2

useRussian = input("Would you like to speak Russian (Y/N): ")

3

if useRussian == 'Y':

4lang = 'ru'

5else:

6lang = 'en'

In [39]:

1 lang = 'en'

2 print(lang)

3 set_lang()

4 print(lang)

en

Would you like to speak Russian (Y/N): N en

Как видим, эта функция не работает — собственно, и не должна. Чтобы функция set_lang смогла менять значение переменной lang , её необходимо явно объявить как глобальную с помощью ключевого слова global .

In [40]:

1 def set_lang():

2global lang

3 useRussian = input("Would you like to speak Russian (Y/N): ") 4 if useRussian == 'Y':

5lang = 'ru'

6else:

7lang = 'en'

In [43]:

1 lang = 'en'

2 print(lang)

3 set_lang()

4 print(lang)

en

Would you like to speak Russian (Y/N): Y ru

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/7. Функции.ipynb

12/17

15.10.2022, 11:11

7. Функции - Jupyter Notebook

Теперь всё работает!

Передача аргументов

Есть разные способы передавать аргументы функции. С одним из них мы уже знакомы:

In [44]:

1 def hello(name, title):

2print("Hello", title, name)

In [45]:

1 hello("Potter", "Mr.")

Hello Mr. Potter

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

In [46]:

1 hello("Harry")

---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

<ipython-input-46-4266b7e1b9aa> in <module>

----> 1 hello("Harry")

TypeError: hello() missing 1 required positional argument: 'title'

Это неудивительно: мы сказали, что функция hello() должна использовать аргумент title , но не передали его — какое же значение тогда использовать? Для преодоления этой трудности используютя значения по умолчанию (default values).

In [48]:

1

def hello(name, title=""):

2

print("Hello", title, name)

3

hello("Harry")

 

 

Hello Harry

In [49]:

1 hello("Smith", "Mrs.")

Hello Mrs. Smith

Аргументы можно передавать, указывая их имена.

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/7. Функции.ipynb

13/17

15.10.2022, 11:11

7. Функции - Jupyter Notebook

In [50]:

 

1

hello("Smith", title = "Mr.")

 

Hello Mr. Smith

 

In [51]:

 

1

hello(name = "Smith", title= "Mr.")

 

Hello Mr. Smith

В этом случае порядок будет неважен.

In [89]:

1 hello(title= "Mr.", name = "Smith")

Hello Mr. Smith

Ещё бывают функции, которые принимают неограниченное число аргументов. Например, так ведёт себя функция print() .

In [61]:

1 print(8, 7, 5, 'hello', 8)

8 7 5 hello 8

Как она устроена? Примерно вот так:

In [52]:

1 def my_print(*args):

2for x in args:

3print(x)

In [53]:

1 my_print(6, 8, 9, 'hello', 88, 55)

6

8

9 hello 88 55

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

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/7. Функции.ipynb

14/17

15.10.2022, 11:11

7. Функции - Jupyter Notebook

In [54]:

1 def test(*args):

2print(args)

3 test(1,2,3, 'hello')

(1, 2, 3, 'hello')

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

Отступление: кортежи

Кортеж ( tuple ) — это почти то же самое, что и список, только его элементы неизменяемы. Обозначается он круглыми скобками.

In [92]:

1 t = (2,3, 5, 1) 2 print(t[1])

3 print(t[0:2])

3 (2, 3)

In [97]:

1 for x in t:

2print(x)

2

3

5

1

In [93]:

1 t[0] = 10

---------------------------------------------------------------------------

TypeError Traceback (most recent call last) <ipython-input-93-eaf187d38884> in <module>()

----> 1 t[0] = 10

TypeError: 'tuple' object does not support item assignment

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/7. Функции.ipynb

15/17

15.10.2022, 11:11 7. Функции - Jupyter Notebook

In [94]:

1 t.append(1)

---------------------------------------------------------------------------

AttributeError Traceback (most recent call last) <ipython-input-94-2337caf868e4> in <module>()

----> 1 t.append(1)

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

Тот факт, что нельзя изменять кортеж, не означает, что нельзя переопределить переменную t :

In [99]:

1 t = (8, 1, 2, 3)

In [100]:

1 t

Out[100]:

(8, 1, 2, 3)

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

Можно также конвертировать списки в кортежи и наоборот.

In [101]:

1 print( list( (1, 2, 3) ) )

2 print( tuple( [1, 2, 3] ) )

[1, 2, 3] (1, 2, 3)

Возвращаясь к функциям

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

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/7. Функции.ipynb

16/17

15.10.2022, 11:11

7. Функции - Jupyter Notebook

In [56]:

 

1

 

def test1(*args):

 

 

 

2

 

 

print(args)

 

3

 

test1(1, 2, 3)

 

4

 

 

 

 

5

 

def test2(args):

 

6

 

 

print(args)

 

7

 

test2( (1,2,3) )

 

 

 

 

 

 

(1,

2,

3)

 

(1,

2,

3)

 

Можно комбинировать списочные переменные и обычные (при условии, что переменная со звёздочкой только одна):

In [57]:

1 def my_print(sep, *args):

2for x in args:

3 print(x, end = sep)

4

In [58]:

 

 

 

 

 

 

1

my_print('

----', 7, 8, 9, 'hello')

 

 

 

 

 

7

----8----

9----

hello----

На сегодня всё :)

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/7. Функции.ipynb

17/17