Заметки по книге "Простой python" [Глава 1-4]


Глава 1. Python: с чем его едят

Created: Jan 24, 2021 11:27 AM

В книге пример с youtube, но ссылка похоже очень старая и уже давно не работает - https://gdata.youtube.com/feeds/api/standardfeeds/top_rated?alt=json

В место нее я использовал json placeholder - https://jsonplaceholder.typicode.com/users

Без библиотеки requests


import json # Импорт всей библиотеки json
from urllib.request import urlopen

url = "https://jsonplaceholder.typicode.com/users"

response = urlopen(url)
content = response.read()
text = content.decode('utf8')
data = json.loads(text)

for user in data:
   print(user['username'], ' - ', user['email'], ' - ', user['phone'])
  • exp
    1. Импорт всей библиотеки json
    2. Импорт только функции urlopen из либы urllib.request
    3. Присвоение переменной значения с url до api
    4. Делаем запрос на сервер
    5. Записываем ответ от сервера в переменную content
    6. Декодим ответ от сервера
    7. Преобразуем строку с json в структуру для работы в python
    8. Цикл по списку пользователей
    9. Вывод данных о юзере
  • пример json-а

    
      [
        {
          "username": "Bret",
          "email": "Sincere@april.biz",
          "phone": "1-770-736-8031 x56442"
        },
        {
          "username": "Antonette",
          "email": "Shanna@melissa.tv",
          "phone": "010-692-6593 x09125"
        },
      ]
      

С библиотекой


import requests
url = "https://jsonplaceholder.typicode.com/users"

response = requests.get(url)
data = response.json()
for user in data:
    print(user['username'], ' - ', user['email'], ' - ', user['phone'])
  • exp
    1. Импорт всей библиотеки requests
    2. Присвоение переменной значения url-а
    3. Выполнение запроса
    4. Пока не знаю
    5. Вывод информации о пользователе

ответ


$ python3 request_example.py 
Bret  -  Sincere@april.biz  -  1-770-736-8031 x56442
Antonette  -  Shanna@melissa.tv  -  010-692-6593 x09125
Samantha  -  Nathan@yesenia.net  -  1-463-123-4447
Karianne  -  Julianne.OConner@kory.org  -  493-170-9623 x156
Kamren  -  Lucio_Hettinger@annie.ca  -  (254)954-1289
Leopoldo_Corkery  -  Karley_Dach@jasper.info  -  1-477-935-8478 x6430
Elwyn.Skiles  -  Telly.Hoeger@billy.biz  -  210.067.6132
Maxime_Nienow  -  Sherwood@rosamond.me  -  586.493.6943 x140
Delphine  -  Chaim_McDermott@dana.io  -  (775)976-6794 x41206
Moriah.Stanton  -  Rey.Padberg@karina.biz  -  024-648-3804

Глава 2. Ингредиенты Python: числа, строки и переменные

Created: Jan 24, 2021 11:27 AM

Присваивание переменной


>>> a = 2
>>> print(a)
2
>>> b = a
>>> print(b)
2
>>>

Узнать тип переменной type


>>> type(a)
<class 'int'>
>>> type(b)
<class 'int'>
>>> type(21)
<class 'int'>
>>> type(9.9)
<class 'float'>
>>> type('dsa')
<class 'str'>
>>>

Зарезервированные слова

Зарезервированные слова

Числа

Целые числа (int)

Пример


>>> 58
58
>>> a = 58
>>> print(a)
58
>>> type(a)
<class 'int'>
>>>

Преобразование в целое число int


>>> int(True)
1
>>> int(89.2)
89
>>> int('89')
89
>>>

Преобразовать строку к Int можно только если в строке валидное число Иначе будет исключение


>>> int('89.2')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '89.2'

Дробные числа (float)

Пример


>>> 89.2
89.2
>>> b = 25.3
>>> print(b)
25.3
>>> type(b)
<class 'float'>
>>>

Преобразование в дробное число float


>>> float(True)
1.0
>>> float(89)
89.0
>>> float('89')
89.0
>>> float('89.1')
89.1

Тоже самое и с дробным числом


>>> float('89.1a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not convert string to float: '89.1a'
>>>

Операторы

Операторы

Строки

Пример


>>> 'text'
'text'
>>> c = 'text'
>>> print(c)
text
>>> type(c)
<class 'str'>
>>> c = "text"
>>> type(c)
<class 'str'>
>>>

Многострочный текст


>>> '''hello
... world'''
'hello\nworld'
>>> a = '''hello
... world'''
>>> print(a)
hello
world
>>>

Преобразование в строку str

пример


>>> str(12)
'12'
>>> str(True)
'True'
>>> str(89.2)
'89.2'
>>>

Конкатенация +


>>> "hello" + " world"
'hello world'
>>>

Умножение строки *


>>> 'test ' * 3
'test test test '
>>>

Посимвольное обращение к строке []


>>> text = "Lorem ipsum dolor sit amet"
>>> text[0] -- первый символ
'L'
>>> text[-1] -- последний символ
't'
>>> text[0:3] -- 3 символа с начала
'Lor'
>>> text[:-1] -- Вырезать последний символ
'Lorem ipsum dolor sit ame'
>>>

При выходе за пределы строки, происходит ошибка


>>> text[100]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range
>>>

Обращение к подстроке [ start : end : step]

  • Оператор [:] возвращает всю строку
  • Оператор [start:] - от start до конца
  • Оператор [:end] - от начала строки до end - 1
  • Оператор [start:end] - от start до end
  • Оператор [start:end:step] - от start до end с шагом step

Развернуть строку


>>> text[-1::-1]
'tema tis rolod muspi meroL'
>>>

Длина строки len


>>> len(text)
26
>>>

Разбить строку split


>>> text.split(' ')
['Lorem', 'ipsum', 'dolor', 'sit', 'amet']
>>>

Объединить строку join


>>> split_text = text.split(' ')
>>> ', '.join(split_text)
'Lorem, ipsum, dolor, sit, amet'
>>>

Начинается с ? startswith


>>> text.startswith('Lorem')
True
>>> text.startswith('Lor')
True
>>> text.startswith('Lor1')
False
>>>

Заканчивается на ? endwith


>>> text.endswith('amet')
True
>>> text.endswith('am')
False
>>>

find

rfind

count

isallnum

Регистр, выравнивание, замена строки

strip

capitalize

title

upper

lower

swapcase

center

ljust

rjust

replace

Глава 3: Наполнение Python: списки, кортежи, словари и множества

Created: Jan 24, 2021 11:27 AM

Списки

Создание списка - [] или метод list()

Примеры списков


>>> empty_list = []
>>> print(empty_list)
[]
>>> test_list = list()
>>> print(test_list)
[]
>>> week_days = ['пн', 'вт']
>>> print(week_days)
['пн', 'вт']
>>>

Элементы списка могут повторятся


>>> uniq_list = ['test1', 'test2', 'test1']
>>> print(uniq_list)
['test1', 'test2', 'test1']

Обращение к элементам списка


>>> uniq_list = ['test1', 'test2', 'test3']
>>> print(uniq_list[1])
test2
>>> print(uniq_list[-1]) # Последний эл. списка
test3

При обращении к эл. списка которого нет - исключение


>>> print(uniq_list[3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

Обращение к диапазону эл. и их замена


>>> list
['test1', 'test2', 'test3']
>>> list[1:3]
['test2', 'test3']
>>> list[1:3] = ['test3', 1]
>>> list
['test1', 'test3', 1]
>>> list[1:3] = ['test3'] # Если не указать значение то эл. удалиться
>>> list
['test1', 'test3']
>>> list[1:3] = ['test3', 1, 2] # если указать больше - добавиться
>>> list
['test1', 'test3', 1, 2]

Инверсия списка


>>> list = [1,2,3,4,5]
>>> list[::-1]
[5, 4, 3, 2, 1]

Многоуровневые списки


>>> list1 = ['test1', 'test2', 'test3']
>>> list2 = ['test4', 'test5', 'test6']
>>> list3 = [list1, li
license(  list(     list1     list2     
>>> list3 = [list1, list2]
>>> print(list3)
[['test1', 'test2', 'test3'], ['test4', 'test5', 'test6']]
>>> print(list3[1][2])
test6

Эл. списка можно менять, а эл. строки - нельзя!


>>> list = ['test1', 'test2', 'test3']
>>> list
['test1', 'test2', 'test3']
>>> list[0] = 'test4'
>>> list
['test4', 'test2', 'test3']
>>> str = 'test'
>>> str[0] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

Добавление в список

в конец - append


>>> list = [1,2,3]
>>> list.append(4)
>>> list
[1, 2, 3, 4]

В начало списка = insert(0)


>>> list = [1,2,3]
>>> list.insert(0, 0)
>>> list
[0, 1, 2, 3]

Также в конец списка - insert(len(), object)


>>> list.insert(len(list), 4)
>>> list
[0, 1, 2, 3, 4]

Удаление из списка: del и remove

del


>>> list = [1,2,3]
>>> list
[1, 2, 3]
>>> del list[0]
>>> list
[2, 3]

remove


>>> list1 = ['test1', 'test2', 'test3']
>>> list1.remove('test1')
>>> list1
['test2', 'test3']

Вернуть эл. из списка и удалить его: pop

Вернуть 1-й эл


>>> list1 = [1,2,3]
>>> list1.pop(0)
1
>>> list1
[2, 3]

Вернуть последний эл.


>>> list1 = [1,2,3]
>>> list1.pop()
3
>>> list1.pop(-1)
2

Вернуть n-й эл.


>>> list1 = [1,2,3]
>>> list1.pop(1)
2
>>> list1

Узнать позицию эл. в списке: index


>>> list1 = ['test1', 'test2', 'test3']
>>> list1.index('test2')
1

Если будет 2 одинаковых эл. то вернется 1-й индекс


>>> list1 = ['test1', 'test2', 'test3', 'test1', 'test2']
>>> list1.index('test2')
1

Если не будет найден эл. - исключение


>>> list1 = ['test1', 'test2', 'test3', 'test1', 'test2']
>>> list1.index('test')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 'test' is not in list

Узнать есть ли эл. в списке: in


>>> list1 = ['test1', 'test2', 'test3']
>>> 'test1' in list1
True
>>> 'test5' in list1
False

Скопировать список: copy, list, [:]

copy


>>> list1 = ['test1', 'test2', 'test3
>>> list2 = list1.copy()
>>> list2
['test1', 'test2', 'test3']

list


>>> list1 = ['test1', 'test2', 'test3']
>>> list2 = list(list1)
>>> list2
['test1', 'test2', 'test3']
>>> list1.append('test4')
>>> list1
['test1', 'test2', 'test3', 'test4']
>>> list2
['test1', 'test2', 'test3']

[:]


>>> list1 = ['test1', 'test2', 'test3']
>>> list2 = list1[:]
>>> list1
['test1', 'test2', 'test3']
>>> list1.append('test4')
>>> list1
['test1', 'test2', 'test3', 'test4']
>>> list2
['test1', 'test2', 'test3']

Кортежи

Создание кортежа: ()


>>> empty_tuple = ()
>>> empty_tuple
()
>>>

еще


>>> tuple = ('test1', 'test2', 'test3')
>>> tuple
('test1', 'test2', 'test3')
>>> tuple2 = 'test1', 'test2', 'test3'
>>> tuple
('test1', 'test2', 'test3')
>>> tuple2
('test1', 'test2', 'test3')

Можно вывести в переменные


>>> tuple = ('test1', 'test2', 'test3')
>>> t1, t2, t3 = tuple
>>> t1
'test1'
>>> t2
'test2'
>>> t3
'test3'

(Как и списки)


>>> list = ['test1', 'test2', 'test3']
>>> t1, t2, t3 = list
>>> t1
'test1'

Поменять значение 2-х переменных


>>> test1 = 'test3'
>>> test3 = 'test1'
>>> test1, test3
('test3', 'test1')
>>> test1, test3 = test3, test1
>>> test1, test3
('test1', 'test3')

Как и списки, кортежи можно объединить через +=


>>> test_tuple1 = 'test1', 'test2'
>>> test_tuple2 = 'test3', 'test4'
>>> test_tuple1 += test_tuple2
>>> test_tuple1
('test1', 'test2', 'test3', 'test4')
>>>

Словари

Создание словаря: {}


>>> empty_dict = {}
>>> empty_dict
{}
>>> dict = {'test1': 1, 'test2': 2}
>>> dict
{'test2': 2, 'test1': 1}

Преобразование в словарь: dict()


>>> list1 = [['test1', 'test2']]
>>> dict(list1)
{'test1': 'test2'}
>>> list1 = [['test1', 'test2'], ['test3', 1]]
>>> dict(list1)
{'test3': 1, 'test1': 'test2'}

Добавление/изменения эл. в словаре: []

Добавить


>>> test_dict = {'test1': 1, 'test2': 2}
>>> test_dict
{'test1': 1, 'test2': 2}
>>> test_dict['test3'] = 3
>>> test_dict
{'test3': 3, 'test1': 1, 'test2': 2}

Обновить


>>> test_dict = {'test1': 1, 'test2': 2}
>>> test_dict['test1'] = 3
>>> test_dict
{'test1': 3, 'test2': 2}

Удалить эл. словаря: del


>>> test_dict1 = {'test1': 1, 'test2': 2}
>>> del test_dict['test1']
>>> test_dict
{'test2': 2}

Множества

Множество - список из уникальных значений

Создание множества: set()


>>> empty_set = set()
>>> empty_set
set()
>>> test_set = {1,2,3,4,4}
>>> test_set
{1, 2, 3, 4}

Преобразовать в множеств

Срока превращается в множество из уникальных значений


>>> set('hello')
{'l', 'e', 'o', 'h'}

Список - в уникальное множество


>>> set(['test1', 'test2', 'test3', 'test1'])
{'test3', 'test2', 'test1'}

Словарь - в уникальное множество из ключей словаря


>>> test_dict = {'test1': 1, 'test2': 2, 'test3': 3}
>>> set(test_dict)
{'test2', 'test3', 'test1'}
# В принципе тоже самое что и keys, только множество
>>> test_dict = {'test1': 1, 'test2': 2, 'test3': 3}
>>> list(test_dict.keys())
['test3', 'test2', 'test1']

Словарь значений - в уникальное множество из значений словаря


>>> test_dict = {'test1': 1, 'test2': 2, 'test3': 1}
>>> set(test_dict.values())
{1, 2}

Глава 4: Корочка Python: структуры кода

Created: Jan 24, 2021 11:27 AM

Комментарии: #


>>> # Коммент
... 2 + 1
3
>>>

Продолжение строки: \


>>> 2 + 1 + \
... 3
6
>>>

Операторы: if, elif, else

if


a = True

if a:
    print("a is True")
else:
    print("a is False")
$ python3 ./test.py 
a is True

Много if


a = False
b = False

if a:
    if b:
        print("a and b is True")
    else:
        print("a is True and b is False")
else:
    if b:
        print("a is False and b is True")
    else:
        print("a and b is False")

$ python3 ./test.py 
a and b is False

elif


color = "green"

if color == "red":
    print("color is red")
elif color == "green":
    print("color is green")
else:
    print("color is other color")

Булево сравнение: and or !

  • = - равенство

>>> x = 7
>>> x == 7
True
>>> x == 5
False
  • != - неравенство

>>> x != 5
True
>>> x != 7
False
  • < - меньше

>>> x < 5
False
>>> x < 10
True
>>> x < 7
False
  • <= - меньше или равно

>>> x <= 10
True
>>> x <= 7
True
>>> x <= 5
False
    • больше

>>> x > 5
True
>>> x > 7
False
>>> x > 10
False
  • = - больше или равно


>>> x >= 5
True
>>> x >= 7
True
>>> x > 10
False
  • in - включение

>>> numbers = [1,2,3]
>>> 2 in numbers
True
>>> 7 in numbers
False

  • and

>>> x > 5 and x < 10
True
>>> x > 10 and x < 10
False
  • or

>>> x > 5 or x > 10
True

Что есть ложь?

  • Булева переменная False
  • Значение None
  • Целое число 0
  • Дробное число 0.0
  • пустая строка (‘’)
  • пустой список ([])
  • пустой кортеж (())
  • пустой словарь ({})
  • пустое множество (set())

Все остальное - истина!

Оператор: while


count = 1
while count <= 5:
    print(count)
    count += 1

$ python3 ./test.py 
1
2
3
4
5

break


while True:
    str = input("Введите символ [q для выхода]: ")
    if str == "q":
        break
    print(str.capitalize())

$ python3 ./test.py 
Введите символ [q для выхода]: w
W
Введите символ [q для выхода]: ee
Ee
Введите символ [q для выхода]: привет
Привет
Введите символ [q для выхода]: привет как дела?
Привет как дела?
Введите символ [q для выхода]: q

continue


while True:
    val = input("Введите число [q для выхода]: ")
    if val == "q":
        break
    number = int(val)
    if number % 2 == 0:
        continue
    print(number, " Квадрат числа ", number*number )

$ python3 ./test.py 
Введите число [q для выхода]: 1
1  Квадрат числа  1
Введите число [q для выхода]: 2
Введите число [q для выхода]: 3
3  Квадрат числа  9
Введите число [q для выхода]: 4
Введите число [q для выхода]: 5
5  Квадрат числа  25
Введите число [q для выхода]: 6
Введите число [q для выхода]: 7
7  Квадрат числа  49
Введите число [q для выхода]:

else


numbers = [1, 3, 5, 2]
index = 0
while index < len(numbers):
    number = numbers[index]
    if number % 2 == 0:
        print("Есть четное число!", number)
        break
    index += 1
else:
    print("Не найдено четных чисел")

Если не был вызов break, то перейдет в else

Оператор: for


>>> test_list = ['test1', 'test2', 'test3']
>>> for item in test_list:
...     print(item)
... 
test1
test2
test3
>>>

если по строке - то цикл по символьно


>>> for letter in 'hello, world!':
...     print(letter)
... 
h
e
l
l
o
,
 
w
o
r
l
d
!

по словарю, по умолчанию вернет ключи


>>> test_dict = {'test1': 1, 'test2': 2, 'test3': 3}
>>> for key in test_dict:
...     print(key)
... 
test1
test3
test2

по значениям


>>> test_dict = {'test1': 1, 'test2': 2, 'test3': 3}
>>> for val in test_dict.values():
...     print(val)
... 
1
3
2

по ключам и значениям


>>> for key, val in test_dict.items():
...     print("Key is '", key, "' Value is '", val, "'")
... 
Key is ' test1 ' Value is ' 1 '
Key is ' test3 ' Value is ' 3 '
Key is ' test2 ' Value is ' 2 '

else


test_list = ['test1', 'test2', 'test3']

for item in test_list:
    print(item)
    if item == 'test2':
        break
else:
    print("test")

$ python3 ./test.py 
test1
test2

Если не был вызван break, то будет else

Включения


>>> test_list = [n for n in range(1,6)]
>>> test_list
[1, 2, 3, 4, 5]

Список из не четных чисел, к которым делается +10


>>> [n + 10 for n in range(1,6) if n % 2 == 1]
[11, 13, 15]

Включение словаря


>>> word = 'hello, world!'
>>> {letter: word.count(letter) for letter in word}
{'r': 1, 'l': 3, 'w': 1, ' ': 1, 'h': 1, ',': 1, '!': 1, 'o': 2, 'e': 1, 'd': 1}

Без вызова count() дважды на одну букву - убрать дубли через set()


>>> {letter: word.count(letter) for letter in set(word)}
{'r': 1, 'l': 3, 'w': 1, 'd': 1, 'h': 1, ',': 1, '!': 1, 'o': 2, 'e': 1, ' ': 1}

Убрать пробел


>>> {letter: word.count(letter) for letter in set(word) if letter != ' '}
{'r': 1, 'l': 3, 'w': 1, 'd': 1, 'h': 1, ',': 1, '!': 1, 'o': 2, 'e': 1}

Функции


def do_nothing():
    pass

do_nothing()

def test_print():
    print('test_print in def test_print')

test_print()

$ python3 ./test.py 
test_print in def test_print

Ответ

Если не указан return, то вернется None


>>> def test_return():
...     1 + 1
... 
>>> print(test_return())
None

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


def check_color(color):
    if color == "red":
        return "color is red"
    elif color == "green":
        return "color is green"
    else:
        return "color is other color"
    
print(check_color("red"))
print(check_color("green"))
$ python3 ./test.py 
color is red
color is green

None это undef?


def test():
    pass

print(test())

$ python3 ./test.py 
None

>>> def is_none(var):
...     if var is None:
...         print("It's None")
...     elif var:
...         print("It's True")
...     else:
...         print("It's False")
... 
>>> is_none(None)
It's None
>>> is_none(True)
It's True
>>> is_none(False)
It's False
>>> is_none([])
It's False
>>> is_none(())
It's False
>>> is_none([])
It's False
>>> is_none(0)
It's False
>>> is_none(0.0)
It's False
>>> is_none('')
It's False
>>> is_none("")
It's False

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


>>> def test_position(t1, t2, t3):
...     return {'test1': t1, 'test2': t2, 'test3': t3}
... 
>>> test_position(1,2,3)
{'test1': 1, 'test3': 3, 'test2': 2}
>>> test_position('a','b','c')
{'test1': 'a', 'test3': 'c', 'test2': 'b'}

Порядок важен, и кол-во аргументов важно. Если не будет хотяб 1, то исключение -


>>> test_position('a','b')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test_position() missing 1 required positional argument: 't3'

больше тоже плохо


>>> test_position(1,2,3,4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test_position() takes 3 positional arguments but 4 were given

Аргументы key = value

Чтобы не сломалась последовательность, можно указать какая переменная чему равна


>>> def test_position(t1, t2, t3):
...     return {'test1': t1, 'test2': t2, 'test3': t3}
... 
>>> test_position(t2 = 1, t3 = 2, t1 = 3)
{'test1': 3, 'test3': 2, 'test2': 1}

Также нельзя ни больше, ни меньше. Если будет 2 раза - исключение


>>> test_position(t2 = 1, t3 = 2, t1 = 3, t2 = 2)
  File "<stdin>", line 1
SyntaxError: keyword argument repeated

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


>>> def test_position(t1, t2, t3 = 't3'):
...     return {'test1': t1, 'test2': t2, 'test3': t3}
... 
>>> test_position(t2 = 1, t1 = 1)
{'test1': 1, 'test3': 't3', 'test2': 1}

Дефолтные значения не чистятся!


def test_result(item, result=[]):
    result.append(item)
    return result

print(test_result(1))
print(test_result(2))

Можно проверить на None перед запуском


def test_result(args, result=None):
    if result is None:
        result = []
    result.append(args)
    return result

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

$ python3 ./test.py 
[1]
[2]
[1, 2, 3]

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

Обычно пишется как *args

args - будет неизменяемый кортеж (tuple)

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


def test_ask(*arg):
    print("Args is ", arg)

test_ask()
test_ask(1)
test_ask(1,2,3)

$ python3 test.py 
Args is  ()
Args is  (1,)
Args is  (1, 2, 3)

удобно использовать как список “остальных” аргументов


def test_req(var1, var2, *args):
    print("Var1 is required", var1)
    print("Var2 is required", var2)
    print("Other params = ", args)

test_req('test1', 'test2', 'other test3')

Порядок при этом важен!

Если будет


def test_req(*args, var1, var2):

то при обращении к функции - исключение


$ python3 test.py 
Traceback (most recent call last):
  File "test.py", line 9, in <module>
    test_req('other test3', 'test1', 'test2')
TypeError: test_req() missing 2 required keyword-only arguments: 'var1' and 'var2'

Также нельзя установить по умолчанию


def test_req(var1, var2, *args = (1)):
    print("Var1 is required", var1)

$ python3 test.py 
  File "test.py", line 4
    def test_req(var1, var2, *args = (1)):
                                   ^
SyntaxError: invalid syntax

Аргументы через ** - словарь

Тоже самое что и кортеж всех остальных, только ключи почему-то должны быть не строкой?


def test_req(val1, **kwargs):
    print("Val1 is required", val1)
    print("Other key/value params = ", kwargs)
    print()

test_req(1, test1=1, test2=1, other_test3=1, yet_yet_yet = 3)

$ python3 test.py 
Val1 is required 1
Other key/value params =  {'test1': 1, 'test2': 1, 'other_test3': 1, 'yet_yet_yet': 3}

Дока к функциям: help


>>> def return1(var):
...     'Вернуть 1-й аргумент'
...     return(var)
... 
>>> help(return1)

Help on function return1 in module __main__:

return1(var)
    Вернуть 1-й аргумент
(END)

def print_if_true(var, check):
    '''
    Вывести первый аргумент если второй аргумент равен True
    Аргументы:
        1. *var* - переменная которую нужно вывести
        2. *check* - переменная по которой проверяется
    '''
    if check:
        print(var)

help(print_if_true)

Help on function print_if_true in module __main__:

print_if_true(var, check)
    Вывести первый аргумент если второй аргумент равен True
    Аргументы:
        1. *var* - переменная которую нужно вывести
        2. *check* - переменная по которой проверяется
(END)

Вывод похож на man страницу. Чтоб вывести как строку


>>> print(return1.__doc__)
Вернуть 1-й аргумент
>>>

print(print_if_true.__doc__)

$ python3 test.py 

    Вывести первый аргумент если второй аргумент равен True
    Аргументы:
        1. *var* - переменная которую нужно вывести
        2. *check* - переменная по которой проверяется

Функции - объекты первого класса. Поэтому можно передавать как аргументы


>>> def test():
...     pass
...
>>> type(test)
<class 'function'>

Можно передать функцию как аргумент другой функции


>>> def answer():
...     print(42)
... 
>>> def run_func(func):
...     func()
... 
>>> run_func(answer)
42

с аргументами


def sum_two(arg1, arg2):
    print(arg1 + arg2)

def run_two(func, v1, v2):
    func(v1, v2)

run_two(sum_two, 4, 5)

$ python3 test.py 
9

Функция в функции


def test_func1():
    def test_func2():
        print("Hello in func2")

    test_func2()
    print("Hello in func1")

test_func1()

$ python3 test.py 
Hello in func2
Hello in func1

Замыкания

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


>>> def say_func(saying):
...     def print_say():
...         print(saying)
...     return print_say
... 
>>> a = say_func('test1')

a - будет ссылкой на функцию внутри другой функции


>>> print(a)
<function say_func.<locals>.print_say at 0x7fc7afc59c80>

Если вызвать - то вызовиться print_say


>>> a()
test1

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


test_list = []

def say_func():
    def print_say():
        test_list.append(1)
    return print_say

a = say_func()
b = say_func()
a()
b()

print(test_list)

$ python3 ./test.py 
[1, 1]

Но у каждого замыкания будет своя локальная переменная


def say_func():
    test_list = []
    def print_say(item):
        test_list.append(item)
        print(test_list)
    return print_say

a = say_func()
b = say_func()
a(1)
b(2)
a('hello')
b('world')

Анонимные функции: lambda()


def edit_text(text, func):
    for word in text:
        func(word)

def edit_word(word):
    print(word.capitalize() + '!')

text = ['привет', 'я', 'список', 'слов', 'которые', 'нужно', 'изменить']
edit_text(text, edit_word)
  • edit_text - принимает текст и функцию
    • Для каждого слова в списке вызывается функция
  • edit_word - принимает слово
    • выводит слово с большой буквы и с восклицательным знаком
  • edit_text(text, edit_word) - передаем текст и функцию

$ python3 ./test.py 
Привет!
Я!
Список!
Слов!
Которые!
Нужно!
Изменить!

тоже самое но через лямбду


def edit_text(text, func):
    for word in text:
        func(word)

text = ['привет', 'я', 'список', 'слов', 'которые', 'нужно', 'изменить']

edit_text(text, lambda word: print(word.capitalize() + '!'))
  • От слова lambda до двоеточия (:) - список аргументов.
  • От : до закрывающей скобки - тело функции

можно даже в переменную сохранить))


>>> a = lambda : 1
>>> a
<function <lambda> at 0x7fc7afc59d08>
>>> a()
1

Генераторы

Особый тип списков - генераторы


>>> sum(range(1, 10))
45

>>> def my_range(start = 0, end = 10, step = 1):
...     number = start
...     while number < end:
...         yield number
...         number += step
...
>>> print(my_range)
<function my_range at 0x7f88811ac9d8>

че такое интересно yield ?


>>> r = my_range(1,5)
>>> print(r)
<generator object my_range at 0x7f88811c4468>

Смысл генератора - один раз вызвать и он заканчивается)


def my_range(start = 0, end = 10, step = 1):
    number = start
    while number < end:
        yield number
        number += step

a = my_range(2, 10)
b = my_range(10, 20)

for x in b:
    print("B is ", x)
    for i in a:
        print("A is ", i)

Декораторы (обертки над функциями)


def print_debug(func):
    def new_func(*args, **kwargs):
        print("Вызов функции:", func.__name__)
        print("Дока функции:", func.__doc__)
        print("Позиционные аргументы:", args)
        print("Аргументы ключ/значение:", kwargs)
        result = func(*args, **kwargs)
        print("Результат:", result)
        return result
    return new_func

def sum_two(a, b):
    '''
    Функция сложения двух аргументов
    Возвращает сумму двух переданных аргументов
    '''
    return a + b

x = 22
y = 2

print(sum_two(x, y))

debug_func = print_debug(sum_two) # мануальное присваивание декоратора
debug_func(x, y)

24
Вызов функции: sum_two
Дока функции: 
    Функция сложения двух аргументов
    Возвращает сумму двух переданных аргументов
    
Позиционные аргументы: (22, 2)
Аргументы ключ/значение: {}
Результат: 24
  • print_debug - возвращает функцию которая вызывается аж в последней строке

До этого момента это объект функции, но без вызова


debug_func = print_debug(sum_two)
print(debug_func)
<function print_debug.<<locals>.new_func at 0x7f50313b6730>

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

Через декоратор - идет обертка а затем вызов.

Не любой декоратор должен вызывать функцию

Можно добавить @название_декоратора в место мануального присваивания


def print_debug(func):
    print('AAAAAAAAa')
    def new_func(*args, **kwargs):
        print("Вызов функции:", func.__name__)
        print("Дока функции:", func.__doc__)
        print("Позиционные аргументы:", args)
        print("Аргументы ключ/значение:", kwargs)
        result = func(*args, **kwargs)
        print("Результат:", result)
        return result
    print('BBBBB')
    return new_func

@print_debug
def sum_two(a, b):
    '''
    Функция сложения двух аргументов
    Возвращает сумму двух переданных аргументов
    '''
    return a + b

x = 22
y = 2

print(sum_two(x, y))

AAAAAAAAa
BBBBB
Вызов функции: sum_two
Дока функции: 
    Функция сложения двух аргументов
    Возвращает сумму двух переданных аргументов
    
Позиционные аргументы: (22, 2)
Аргументы ключ/значение: {}
Результат: 24
24

Как видно, в начале вызов декоратора, потом вызов функции, потом возврат результата

Можно несколько декораторов


def print_debug(func):
    print('AAAAAAAAa')
    def new_func(*args, **kwargs):
        print("Вызов функции:", func.__name__)
        print("Дока функции:", func.__doc__)
        print("Позиционные аргументы:", args)
        print("Аргументы ключ/значение:", kwargs)
        result = func(*args, **kwargs)
        print("Результат:", result)
        return result
    print('BBBBB')
    return new_func

def square(func):
    def new_func(*args, **kwargs):
        result = func(*args, **kwargs)
        print("Вызов функции возведения в квадрат")
        return result * result
    return new_func

@square
@print_debug
def sum_two(a, b):
    '''
    Функция сложения двух аргументов
    Возвращает сумму двух переданных аргументов
    '''
    return a + b

x = 3
y = 2

print(sum_two(x, y))

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


@print_debug
@square
def sum_two(a, b):
    '''
    Функция сложения двух аргументов
    Возвращает сумму двух переданных аргументов
    '''
    return a + b

x = 3
y = 2

print(sum_two(x, y))

AAAAAAAAa
BBBBB
Вызов функции: new_func
Дока функции: None
Позиционные аргументы: (3, 2)
Аргументы ключ/значение: {}
Вызов функции возведения в квадрат
Результат: 25
25

Пространство имен

  1. Глобальные переменные

hello = 'hello'

def print_hello():
    print(hello)

print_hello()

$ python3 ./test.py 
hello

Можно обращаться, но нельзя изменять!


hello = 'hello'

def print_hello():
    print("Глобольная переменная равна = ", hello)
    hello = 'bye'
    print("Локальная переменная равна = ", hello)
    print(hello)

print_hello()

Traceback (most recent call last):
  File "./test.py", line 11, in <module>
    print_hello()
  File "./test.py", line 6, in print_hello
    print("Глобольная переменная равна = ", hello)
UnboundLocalError: local variable 'hello' referenced before assignment

Но при этом, можно назвать одинаково


hello = 'hello'

def print_hello():
    hello = 'bye'
    print("Локальная переменная равна = ", hello)
    print(hello)

print_hello()
print(hello)

Локальная переменная равна =  bye
bye
hello

gloabl

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


hello = 'hello'

def print_hello():
    global hello
    hello = 'bye'
    print("Локальная переменная равна = ", hello)
    print(hello)

print_hello()
print(hello)

Локальная переменная равна =  bye
bye
bye

hello = 'hello'

def print_hello():
    hello = 'bye'
    print("locals:", locals())

print_hello()

print("globals: ", globals())

locals: {'hello': 'bye'}
globals:  {'__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__cached__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fc265e0e9b0>, '__spec__': None, 'print_hello': <function print_hello at 0x7fc265d792f0>, 'hello': 'hello', '__name__': '__main__', '__file__': './test.py', '__package__': None}
  • locals() - возвращает список локальных имен переменных
  • globals() - возвращает список глобальных имен переменных

Обработка ошибок: try и except

Пример исключения


test_list = [1,2,3]
test_list[4]

Traceback (most recent call last):
  File "./test.py", line 5, in <module>
    test_list[4]
IndexError: list index out of range
avis@avis[20:50:51]:~/learn/python/book-simple-python$

Обработка


test_list = [1,2,3]
index = 4
try:
    test_list[index]
except:
    print("Нужна позиция с 0 до", len(test_list) - 1, "но получено: ", index)

avis@avis[20:52:56]:~/learn/python/book-simple-python$ python3 ./test.py 
Нужна позиция с 0 до 2 но получено:  4

Если не указать тип исключения, то будут ловиться все исключения.

Формат - except тип_исключения as имя


test_list = [1,2,3]

while True:
    index = input("Позиция? [q для выхода]: ")
    if index == 'q':
        break
    try:
        index = int(index)
        print(test_list[index])
    except IndexError as err:
        print("Плохой индекс: ", index)
    except Exception as other:
        print("Другая ошибка: ", other)

Позиция? [q для выхода]: 1
2
Позиция? [q для выхода]: 0
1
Позиция? [q для выхода]: 200
Плохой индекс:  200
Позиция? [q для выхода]: да?
Другая ошибка:  invalid literal for int() with base 10: 'да?'
Позиция? [q для выхода]: ну лад
Другая ошибка:  invalid literal for int() with base 10: 'ну лад'
Позиция? [q для выхода]: 3
Плохой индекс:  3
Позиция? [q для выхода]: й
Другая ошибка:  invalid literal for int() with base 10: 'й'
Позиция? [q для выхода]: q

Собственные исключения


class UppercaseException(Exception):
    pass

text = ['test', 'upper', 'case', 'AAAAAAAA']

for word in text:
    if word.isupper():
        raise UppercaseException(word)

Traceback (most recent call last):
  File "./test.py", line 10, in <module>
    raise UppercaseException(word)
__main__.UppercaseException: AAAAAAAA

Создаем класс и вызываем его если встречаем слово все буквы которого с болькой

Если pass - то выводится стандатное исключение

но можно изменить?


class UppercaseException(Exception):
    print("Почему все с большой????")
    pass

text = ['test', 'upper', 'case', 'AAAAAAAA']

for word in text:
    if word.isupper():
        raise UppercaseException(word)

Почему все с большой????
Traceback (most recent call last):
  File "./test.py", line 11, in <module>
    raise UppercaseException(word)
__main__.UppercaseException: AAAAAAAA