Важные концепции в Python, которые помогают программисту в работе

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Привет, Хабр! Сегодня поговорим о 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

Что здесь происходит? Код выполняет одновременно три функции.

  1. yourfunction(1), yourfunction(2) и yourfunction(3) выполняются одновременно.

  2. yourfunction(4), yourfunction(5) и yourfunction(6) также выполняются одновременно.

  3. 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!

Сейчас мы добавили дополнительный ! после возвращаемого значения.

Генераторы + ключевое слово 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/


Интересные статьи

Интересные статьи

Привет, Хабр! Меня зовут Алексей Колосков, я DevOps/Cloud-инженер в Hilbert Team. Вместе с моим коллегой Михаилом Кажемским в этой статье мы расскажем об особенностях DevSecOps-пайплайна и концепции S...
Многие разработчики считают принципы программирования обязательными и используют их по дефолту во всех проектах. На самом деле большинство из них нереализуемы на практике — докажем это на нескольких п...
Привет, Хабр! Предлагаю вашему вниманию перевод статьи The Languages Which Almost Became CSS автора Zack Bloom про языки, которые могли бы стать CSS, сложись история немного иначе. Н...
В мире разработки программного обеспечения на разработчиков оказывается постоянное давление, принуждающее их писать код вне рабочего времени. Некоторые считают программирование своей страстью, др...
Дело было вечером, делать было нечего. Самое время устроить небольшой разбор того, чем изнутри отличаются некоторые способы перебора массивов в PHP. Исходники от master ветки (это сейчас 7...