Skip to content

Commit

Permalink
describe lists as default values (#36)
Browse files Browse the repository at this point in the history
* describe lists as default values

* improve wording in functions lecture

Co-authored-by: Mark Baushenko <[email protected]>

* remove excessive newlines

* specify snippets language

* remove excessive newline

Co-authored-by: vvssttkk <[email protected]>
Co-authored-by: Mark Baushenko <[email protected]>
  • Loading branch information
3 people authored Oct 6, 2022
1 parent 68c9257 commit 14d93bd
Showing 1 changed file with 109 additions and 18 deletions.
127 changes: 109 additions & 18 deletions docs/base/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def print_theme():
# Выше была определена print_theme, ее и вызовем.
print_theme()
```
```
```bash
Лекция про функции!
Тело кончилось
```
Expand Down Expand Up @@ -152,7 +152,7 @@ def add_two(x):
from_print_theme = print_theme()
print(from_print_theme is None)
```
```
```bash
Лекция про функции!
Тело кончилось
True
Expand All @@ -167,7 +167,7 @@ True
from_add_two = add_two(2)
print(from_add_two)
```
```
```bash
4
```

Expand All @@ -187,7 +187,7 @@ def change_num(num):
print(change_num(4))
print(change_num(5))
```
```
```bash
2
10
```
Expand Down Expand Up @@ -217,7 +217,7 @@ try:
except NameError as ne:
print(ne)
```
```
```bash
name 'result' is not defined
```

Expand Down Expand Up @@ -273,7 +273,7 @@ def foo():

foo()
```
```
```bash
name
10
20
Expand All @@ -299,7 +299,7 @@ def make_adder(arg1):
add_three = make_adder(3)
print(add_three(2))
```
```
```bash
5
```

Expand All @@ -318,7 +318,7 @@ def adder(arg1, arg2):
add_three = partial(adder, 3)
print(add_three(2))
```
```
```bash
5
```

Expand Down Expand Up @@ -431,7 +431,7 @@ print(two_var_sum(-1, 2), two_var_sum(2, -1))
# Указывается название параметра и значение после =
print(two_var_sum(var2=2, var1=-1))
```
```
```bash
3 1
3
```
Expand All @@ -449,7 +449,7 @@ def many_arg_sum(*args):

many_arg_sum(1, 2, 3, 4, 5, 6)
```
```
```bash
21
```

Expand Down Expand Up @@ -484,7 +484,7 @@ hello(phrase="Здарова", name="Игорь")
# Если не указать значение именованного параметра, используется что по умолчанию
hello("Вася")
```
```
```bash
Приветствую, Саша
Здорова, Игорь
Привет, Вася
Expand Down Expand Up @@ -513,14 +513,105 @@ def congrats(today, everyone=False, **names_dates_mapper):

congrats("2021-09-17", Paul="2001-03-08", Lena="1997-01-31", Mark="1997-09-17")
```
```
```bash
Happy Birthday, Mark
```

!!! question "Что это за комментарий в тройных кавычках внутри функции?"

Это один из общепринятых способов написания [docstring](https://www.python.org/dev/peps/pep-0257/) — документации по функции.

### Списки как значения по умолчанию

Рассмотрим следующую функцию:

```python linenums="1"
def fn(ls=[1]):
ls.append(2)
return ls

print(fn())
print(fn())
```
```bash
[1, 2]
[1, 2, 2]
```

Второй вызов функции привел к результату, отличающемуся от первого вызова. Почему так произошло? Значение `ls` по умолчанию мы объявили равным `[1]`. Оба вызова используют значение по умолчанию. Но при втором вызове в данном случае произошло обращение к тому же списку, который был создан в качестве значения по умолчанию при первом вызове. Как это можно проверить?

В Python определена встроенная функция [id](https://docs.python.org/3/library/functions.html#id). Она возвращает целочисленный идентификатор объекта (уникальный и постоянный, пока объект существует). Используем ее, чтобы посмотреть идентификаторы списков.

```python linenums="1"
def fn_with_id(ls=[1]):
print(id(ls))
ls.append(2)
return ls

print(fn_with_id())
print(fn_with_id())
print(fn_with_id([3]))
print(fn_with_id())
```
```bash
123928376604123
[1, 2]
123928376604123
[1, 2, 2]
113928976643254
[3, 2]
123928376604123
[1, 2, 2, 2]
```

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

Одним из решений может быть следующее:

```python linenums="1"
def fixed_fn(ls=None):
if ls is None:
return [2]

ls.append(2)
return ls

print(fixed_fn())
print(fixed_fn())
print(fixed_fn([1]))
print(fixed_fn())
```
```bash
[2]
[2]
[1, 2]
[2]
```

Обратите внимание, что с `set`-ом ситуация другая.

```python linenums="1"
def fn_with_set(_set=set()):
_set.add(2)
print(id(_set))
return _set

print(fn_with_set())
print(fn_with_set())
print(fn_with_set({3}))
print(fn_with_set())
```
```bash
140214028693696
{2}
140214028693696
{2}
129928985405920
{2, 3}
140214028693696
{2}
```

## Анонимные функции

Функции, определенные при помощи `def`, имеют название, по которому их можно вызвать, но также существуют и анонимные или неименованные функции. Такие функции могут быть определены при помощи оператора `lambda`. Он позволяет задать входные и выходные данные. Самостоятельно можете почитать [документацию](https://docs.python.org/3/reference/expressions.html#grammar-token-lambda-expr).
Expand All @@ -537,7 +628,7 @@ lambda x: abs(x)

lambda num, div=2: "нет" if num % div else "да"
```
```
```bash
<function __main__.<lambda>(num, div=2)>
```

Expand All @@ -555,7 +646,7 @@ print(check_div(3), check_div(5, 5))
# Возможен вызов и без сохранения в переменную
print((lambda x: abs(x))(-120))
```
```
```bash
нет да
120
```
Expand All @@ -567,7 +658,7 @@ print((lambda x: abs(x))(-120))
```python linenums="1"
list(map(lambda x: x**2, [1, 2, 3]))
```
```
```bash
[1, 4, 9]
```

Expand All @@ -579,7 +670,7 @@ list(map(lambda x: x**2, [1, 2, 3]))
perform_computation = lambda: 2 ** 10_000_000 / 2 ** 10_000_000
perform_computation()
```
```
```bash
1.0
```

Expand Down Expand Up @@ -628,7 +719,7 @@ many_arg_sum = time_decorator(many_arg_sum)
# Поведение функции поменялось, а код вызова — нет
summed = many_arg_sum(10, 0, -120, 333)
```
```
```bash
Прошло 1.9073486328125e-06 секунд
```

Expand All @@ -644,7 +735,7 @@ def primitive_exponentiation(x, power=5):

powered = primitive_exponentiation(10)
```
```
```bash
Прошло 4.0531158447265625e-06 секунд
```

Expand Down

0 comments on commit 14d93bd

Please sign in to comment.