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

Мультипроцессинг в Python
Здесь речь идёт о встроенном модуле multiprocessing. Он позволяет запускать более одной функции одновременно. А это бывает весьма полезно.
import time import datetime def yourfunction(x): start = datetime.datetime.now() time.sleep(1) end = datetime.datetime.now() return f'x={x} start at {start}, end at {end}' if __name__ == '__main__': with multiprocessing.Pool(processes=3) as pool: data = pool.map(yourfunction, [1, 2, 3, 4, 5, 6, 7]) for row in data: print(row)
x=1 start at 2023-04-16 13:39:32.035510, end at 2023-04-16 13:39:33.037308
x=2 start at 2023-04-16 13:39:32.035795, end at 2023-04-16 13:39:33.037324
x=3 start at 2023-04-16 13:39:32.037349, end at 2023-04-16 13:39:33.037629
x=4 start at 2023-04-16 13:39:33.037725, end at 2023-04-16 13:39:34.040135
x=5 start at 2023-04-16 13:39:33.037892, end at 2023-04-16 13:39:34.040160
x=6 start at 2023-04-16 13:39:33.037986, end at 2023-04-16 13:39:34.040161
x=7 start at 2023-04-16 13:39:34.040454, end at 2023-04-16 13:39:35.045383
Что здесь происходит? Код выполняет одновременно три функции.
-
yourfunction(1), yourfunction(2) и yourfunction(3) выполняются одновременно.
-
yourfunction(4), yourfunction(5) и yourfunction(6) также выполняются одновременно.
-
yourfunction(7) работает отдельно от других.
Кортежи (tuple) в Python. Обычная распаковка и распаковка кортежа с *
Кортежи (tuple) в Python — неизменяемые структуры данных. Ну а концепция распаковки может быть крайне полезна в ряде случаев.
person = ['bob', 30, 'male'] name, age, gender = person # name='bob', age=30, gender='male'
Так, можно использовать распаковку кортежей для одновременного назначения нескольких переменных. Далее, добавляем * перед переменными для распаковки всего остального в эту переменную.
fruits = ['apple', 'orange', 'pear', 'pineapple', 'durian', 'banana'] first, second, *others = fruits # first='apple', second='orange' # others = ['pear', 'pineapple', 'durian', 'banana']
Тернарный оператор
Тернарный оператор — это оператор, который используется для демонстрации какого-то условия, то есть вместо условной конструкции. Вот как его можно использовать.
score = 57 if score > 90: grade = 'A*' elif score > 50: grade = 'pass' else: grade = 'fail' # grade = 'pass'
Обычный блок if-elif-else.
score = 57 grade = 'A*' if score > 90 else 'pass' if score > 50 else 'fail' # grade = 'pass'
А ещё можно сжать блок if-elif-else в ОДНУ строку, используя тернарный оператор.
Генератор списка + понимание генератора словарей/множеств
А вот практическое применение этой концепции. Так, с генератором списка можно создавать собственный список в одной строке кода.
lis = [expression for i in iterable if condition] l1 = [i for i in range(1,4)] # [1,2,3] l2 = [i*2 for i in range(1,4)] # [2,4,6] l3 = [i**2 for i in range(1,4)] # [1,4,9] l4 = [i for i in range(1,4) if i%2==1]# [1,3]
Также генератор множества и генератор словаря можно применять для создания множеств и словарей таким же образом, как и в случае создания списков, используя генератор списков.
set1 = {i for i in range(1,4)} # {1,2,3} d1 = {i:i**2 for i in range(1,4)} # {1:1, 2:4, 3:9}
* *args и **kwargs
Ещё одна интересная возможность. Так, *args дают возможность функциям принимать любое количество позиционных аргументов. Они будут храниться в кортеже args.
def test(a, b, *args): print(f'{a=} {b=} {args=}') test(1,2,3,4,5) # a=1 b=2 args=(3,4,5)
Ну а **kwargs позволяют функциям принимать любое количество аргументов ключевого слова (которые будут храниться в словаре kwargs).
def test(a, b, **kwargs): print(f'{a=} {b=} {kwargs=}') test(a=1, b=2, c=3, d=4)# a=1 b=2 kwargs={'c': 3, 'd': 4}
Одновременная работа с несколькими .py-файлами
Проблема в том, что даже у не очень занятого разработчика всегда есть несколько проектов с большим количеством разных файлов. Вот так можно обеспечить работу с ними.
# helper.py def test123(): print('test123 is called') # main.py from helper import test123 test123()# test123 is called
if __name__ == ‘__main__’
Ну а здесь речь идёт о том, что строка из заголовка оценивается как True в файле .py. Правда, лишь в том случае, если мы запускаем сам файл напрямую. Строка же используется для того, чтобы случайно не запустить строки кода, которые не планировалось использовать.
# helper.py def test123(): print('test123 is called') if __name__ == '__main__': # this line only runs if we run helper.py DIRECTLY print('print statement from helper.py') # main.py from helper import * test123()# test123 is called
Библиотеки построения веб-API Python
В этом пункте — без кода. Речь о том, что библиотеки эти крайне полезны для разработчика на Python, причём некоторые узнают об их существовании достаточно поздно. Вот две простые для освоения даже начинающими программистами библиотеки на Python:
-
Python FastAPI — простое создание API.
-
Python Flask — создание API и простых веб-приложений при помощи Flask.
Декораторы
О них многие тоже узнают поздно (есть, конечно, и исключения из этого правила). Вот участок кода для примера:
def add_exclamation_mark(your_function): def inner(*args, **kwargs): return your_function(*args, **kwargs) return inner @add_exclamation_mark def greet(name): return f'hello {name}'
Зачем здесь нужен декоратор? Декораторы — функции, которые:
-
принимают другую функцию
-
настраивают работу функции
-
возвращают другую функцию
И когда @add_exclamation_mark ставится над функцией greet, мы меняем работу greet, декорируя её.
# @add_exclamation_mark # def greet(name) # # ^ THIS IS THE SAME AS BELOW: # # greet = add_exclamation_mark(greet) print(greet('tim'))# hello tim!
Из-за декоратора функция greet ведет себя по-другому, и теперь у нее есть дополнительный ! после возвращаемого значения.
Генераторы + ключевое слово yield
Это слово похоже на return. Но за малым исключением — функция в этом случае не останавливается после чего-то. Функция с yield становится функцией-генератором и может иметь несколько выходных данных.
def simple_generator(): yield 'apple' yield 'orange' yield 'pear' for fruit in simple_generator(): print(fruit) # apple orange pear
Лямбда-функции
О них многие знают, но не все используют. На самом деле всё просто.
def add(x, y): return x + y # this is the same as add = lambda x,y : x + y
Мы используем лямбда-функцию, когда нам ненадолго требуется безымянная функция. Вот пример:
def test(): return 'hello' # this is the same as test = lambda : 'hello' def test2(a,b,c,d): return (a+b) / (c-d) # this is the same as test2 = lambda a,b,c,d : (a+b) / (c-d)
Лямбда-функции могут иметь любое количество аргументов, но у каждой может быть только одно выражение. Выражение вычисляется и возвращается. Эти функции могут быть использованы везде, где требуется объект-функция.
assert + raise + custom-исключения
И ещё одна полезная концепция. Здесь ключевое слово assert даёт возможность провести тест на работоспособность в середине кода. Если оценка >100, возникает ошибка AssertionError, после чего программа принудительно завершает работу.
assert score <= 100 # ensuring that score cannot be above 100.
Ключевое слово raise позволяет принудительно вызвать исключение (также можно настроить сообщение в исключении).
if score > 100: raise Exception('score cannot be higher than 100') # ensuring that score cannot be above 100.
Ну и плюс можно создавать свои собственные типы Exception, наследуя от класса Exception.
class ScoreException(Exception): def __init__(self): super().__init__('score cannot be higher than 100') if score > 100: raise ScoreException()
Конечно, в этой подборке указаны далеко не все фишки, которые используют как опытные, так и не очень разработчики практически каждый день. Если у вас есть такая фишка, расскажите о ней в комментариях — порадуйте коллег.
ссылка на оригинал статьи https://habr.com/ru/companies/ru_mts/articles/743918/
Добавить комментарий