🐍⚑ Python для пСрфСкционистов: 10 способов ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΈΠ΄Π΅Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄

ΠŸΡ€ΠΎΡΡ‚ΠΎΡ‚Π° Python позволяСт Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌ быстро ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‡ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Π½ΠΎ Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€ΠΎΠ΄Π²ΠΈΠ½ΡƒΡ‚Ρ‹Π΅ Ρ‚Π΅Ρ…Π½ΠΈΠΊΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ваш ΠΊΠΎΠ΄ Π±ΠΎΠ»Π΅Π΅ эффСктивным, Π³ΠΈΠ±ΠΊΠΈΠΌ ΠΈ элСгантным.

Π­Ρ‚ΠΎΡ‚ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π» взят ΠΈΠ· нашСй СТСнСдСльной email-рассылки, посвящСнной бэкСнду. ΠŸΠΎΠ΄ΠΏΠΈΡˆΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π² числС ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, ΠΊΡ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ дайдТСст.

ИспользованиС дСскрипторов для управлСния доступом ΠΊ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°ΠΌ

ДСскрипторы ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΠΎ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ доступом, Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ΠΌ, записью ΠΈ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ΠΌ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠ² Π² классах. Π­Ρ‚ΠΎ ΠΌΠΎΡ‰Π½Ρ‹ΠΉ инструмСнт для создания Π±ΠΎΠ»Π΅Π΅ Π³ΠΈΠ±ΠΊΠΎΠ³ΠΎ ΠΈ Ρ‡ΠΈΡ‚Π°Π΅ΠΌΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: класс для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ‚ΠΈΠΏΠΎΠ² Ρ‡Π΅Ρ€Π΅Π· дСскриптор

class Typed:
    def __init__(self, name, expected_type):
        self.name = name
        self.expected_type = expected_type

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__.get(self.name)

    def __set__(self, instance, value):
        if not isinstance(value, self.expected_type):
            raise TypeError(f"ΠžΠΆΠΈΠ΄Π°ΡŽΡ‚ΡΡ Π΄Π°Π½Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΠ° {self.expected_type}, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Ρ‹ Π΄Π°Π½Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΠ° {type(value)}")
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        raise AttributeError("НСвозмоТно ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚")

class Person:
    name = Typed("name", str)
    age = Typed("age", int)

    def __init__(self, name, age):
        self.name = name
        self.age = age

try:
    p = Person("Алиса", 10)
    print(p.name)  
    p.age = "10"  
except TypeError as e:
    print(e)

Π’Ρ‹Π²ΠΎΠ΄:

Алиса
ΠžΠΆΠΈΠ΄Π°ΡŽΡ‚ΡΡ Π΄Π°Π½Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΠ° <class 'int'>, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Ρ‹ Π΄Π°Π½Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΠ° <class 'str'>

Π£ΠΏΡ€ΠΎΡ‰Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π° классов с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ dataclass

ИспользованиС dataclass Π² Python – ΡƒΠ΄ΠΎΠ±Π½Ρ‹ΠΉ способ упрощСния ΠΊΠΎΠ΄Π° для классов, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Ρ‹ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для хранСния Π΄Π°Π½Π½Ρ‹Ρ…. ВмСсто Ρ€ΡƒΡ‡Π½ΠΎΠ³ΠΎ опрСдСлСния ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² __init__, __repr__, __eq__ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ…, ΠΌΠΎΠΆΠ½ΠΎ автоматичСски Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ…, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π°Π½Π½ΠΎΡ‚Π°Ρ†ΠΈΠΈ Ρ‚ΠΈΠΏΠΎΠ². ΠŸΡ€Π΅ΠΈΠΌΡƒΡ‰Π΅ΡΡ‚Π²Π° использования dataclass:

  • Π‘ΠΎΠΊΡ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π° – Π½Π΅Ρ‚ нСобходимости Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ Π²Ρ€ΠΎΠ΄Π΅ __init__, __repr__, ΠΈ ΠΈΡ… ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ.
  • Π§ΠΈΡ‚Π°Π΅ΠΌΠΎΡΡ‚ΡŒ – ΠΊΠΎΠ΄ Π»Π΅Π³Ρ‡Π΅ Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ Π²Ρ‹ Π²ΠΈΠ΄ΠΈΡ‚Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ список ΠΏΠΎΠ»Π΅ΠΉ, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΠΈΡ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚.
  • Π“ΠΈΠ±ΠΊΠΎΡΡ‚ΡŒ – ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΈΠ»ΠΈ настройки, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ класса.
  • Автоматизация – встроСнныС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ автоматичСски, Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒ ошибок сводится ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌΡƒ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

from dataclasses import dataclass

@dataclass
class Employee:
    name: str
    last_name: str
    age: int
    position: str

emp = Employee(name="Π•Π²Π³Π΅Π½ΠΈΠΉ", last_name="ОнСгин", age=30, position="бэкСндСр")
print(emp)  
emp2 = Employee(name="ΠŸΡŒΠ΅Ρ€", last_name="Π‘Π΅Π·ΡƒΡ…ΠΎΠ²", age=30, position="Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄Π΅Ρ€")
print(emp == emp2)  
print(repr(emp2))  

Π’Ρ‹Π²ΠΎΠ΄:

Employee(name='Π•Π²Π³Π΅Π½ΠΈΠΉ', last_name='ОнСгин', age=30, position='бэкСндСр')
False
Employee(name='ΠŸΡŒΠ΅Ρ€', last_name='Π‘Π΅Π·ΡƒΡ…ΠΎΠ²', age=30, position='Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄Π΅Ρ€')

ΠšΠ°ΡΡ‚ΠΎΠΌΠ½Ρ‹Π΅ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Ρ‹ контСкста

Когда возмоТностСй стандартного контСкстного ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, open) нСдостаточно, ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ свой, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ спСцифичСскими рСсурсами.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: собствСнный контСкстный ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π±Π°Π·ΠΎΠΉ Π΄Π°Π½Π½Ρ‹Ρ…

import sqlite3
from contextlib import contextmanager
from pathlib import Path

@contextmanager
def open_db(db_path):
    db_path = Path(db_path)
    if not db_path.exists():
        raise FileNotFoundError(f"Π€Π°ΠΉΠ» Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… {db_path} Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½.")

    connection = sqlite3.connect(db_path)
    try:
        yield connection
    finally:
        connection.commit() 
        connection.close()  
db_file = "example.db"
with open_db(db_file) as conn:
    cursor = conn.cursor()
    cursor.execute('''CREATE TABLE IF NOT EXISTS users (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        name TEXT,
                        age INTEGER)''')
    cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ("Π•Π²Π³Π΅Π½ΠΈΠΉ", 30))
    cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ("Π’Π°Ρ‚ΡŒΡΠ½Π°", 25))
    print("Π”Π°Π½Π½Ρ‹Π΅ внСсСны Π² Π±Π°Π·Ρƒ.")

Π’Ρ‹Π²ΠΎΠ΄:

Π”Π°Π½Π½Ρ‹Π΅ внСсСны Π² Π±Π°Π·Ρƒ.

Аннотации Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ

Аннотации Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚, ΠΊΠ°ΠΊΠΈΠ΅ Ρ‚ΠΈΠΏΡ‹ Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‚ΡΡ Π½Π° Π²Ρ…ΠΎΠ΄Π΅ ΠΈ ΠΊΠ°ΠΊΠΎΠΉ Ρ‚ΠΈΠΏ Π±ΡƒΠ΄Π΅Ρ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½. Они Π΄Π΅Π»Π°ΡŽΡ‚ ΠΊΠΎΠ΄ понятнСС, бСзопаснСС ΠΈ ΡƒΠ΄ΠΎΠ±Π½Π΅Π΅ для Ρ€Π°Π±ΠΎΡ‚Ρ‹, ΠΈ особСнно ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ Π² ΠΊΡ€ΡƒΠΏΠ½Ρ‹Ρ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ…, Π³Π΄Π΅ трСбуСтся строгий ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ Ρ‚ΠΈΠΏΠΎΠ² ΠΈ ясноС описаниС повСдСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ. НапримСр, здСсь сразу Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ функция ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ length ΠΈ width Π² Π²ΠΈΠ΄Π΅ чисСл с ΠΏΠ»Π°Π²Π°ΡŽΡ‰Π΅ΠΉ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ float ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ Ρ‚ΠΈΠΏΠ°:

def calculate_area(length: float, width: float) -> float:
    return length * width

МногиС IDE ΠΈ инструмСнты ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ‚ΠΈΠΏΠΎΠ² (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, MyPy) ΠΌΠΎΠ³ΡƒΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π°Π½Π½ΠΎΡ‚Π°Ρ†ΠΈΠΈ для поиска ошибок Π² ΠΊΠΎΠ΄Π΅ Π΅Ρ‰Π΅ Π΄ΠΎ Π΅Π³ΠΎ выполнСния. НапримСр, Ссли Π²Ρ‹ случайно ΠΏΠ΅Ρ€Π΅Π΄Π°Π΄ΠΈΡ‚Π΅ строку вмСсто числа, Ρ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ строка str Π½Π΅ соотвСтствуСт ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ float:

area = calculate_area("5.0", 3.2)  # Ошибка!

Π”Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€Ρ‹ для ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠ³ΠΎ использования ΠΊΠΎΠ΄Π°

Π”Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€Ρ‹ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ ΠΎΡ‚Π΄Π΅Π»ΠΈΡ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π»ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ ΠΏΡ€Π°Π² доступа, ΠΈΠ·ΠΌΠ΅Ρ€Π΅Π½ΠΈΠ΅ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ выполнСния) ΠΎΡ‚ основной Π»ΠΎΠ³ΠΈΠΊΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Π­Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ ΠΊΠΎΠ΄ Π±ΠΎΠ»Π΅Π΅ понятным ΠΈ Π»Π΅Π³ΠΊΠΈΠΌ Π² сопровоТдСнии.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: ΠΈΠ·ΠΌΠ΅Ρ€Π΅Π½ΠΈΠ΅ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ выполнСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ

import time

def measure_time(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"Ѐункция {func.__name__} Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Π·Π° {end - start:.4f} сСкунд")
        return result
    return wrapper

@measure_time
def compute():
    sum(range(10**7))
compute()

Π’Ρ‹Π²ΠΎΠ΄:

Ѐункция compute Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Π·Π° 0.1000 сСкунд

ИспользованиС functools для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ слоТных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ с функциями

ΠœΠΎΠ΄ΡƒΠ»ΡŒ functools – ΠΌΠΎΡ‰Π½Ρ‹ΠΉ инструмСнт, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ:

  • ΠŸΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ (Π·Π° счСт ΠΊΡΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ).
  • ΠžΠ±Π»Π΅Π³Ρ‡Π°Π΅Ρ‚ созданиС Π³ΠΈΠ±ΠΊΠΈΡ… ΠΈ ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ.
  • Π£ΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρƒ с функциями Π²Ρ‹ΡΡˆΠ΅Π³ΠΎ порядка.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: оптимизация ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΡΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ

from functools import lru_cache

@lru_cache(maxsize=100)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(100))  

Π‘Π΅Π· ΠΊΡΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ вычислСниС Π±ΠΎΠ»ΡŒΡˆΠΈΡ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π€ΠΈΠ±ΠΎΠ½Π°Ρ‡Ρ‡ΠΈ Π±Ρ‹Π»ΠΎ Π±Ρ‹ Ρ‡Ρ€Π΅Π·Π²Ρ‹Ρ‡Π°ΠΉΠ½ΠΎ ΠΌΠ΅Π΄Π»Π΅Π½Π½Ρ‹ΠΌ ΠΈΠ·-Π·Π° ΡΠΊΡΠΏΠΎΠ½Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΉ слоТности. Но с lru_cache ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ΡΡ, Ρ‡Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ сокращаСт врСмя выполнСния.

🐍 Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° питониста
Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° питониста»
πŸπŸŽ“ Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python для собСса
ΠŸΠΎΠ΄Ρ‚ΡΠ½ΡƒΡ‚ΡŒ свои знания ΠΏΠΎ Python Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python для собСса»
🐍🧩 Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π°Π΄Π°Ρ‡ ΠΏΠΎ Python
Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½Ρ‹Π΅ Π·Π°Π΄Π°Ρ‡ΠΈ ΠΏΠΎ Python для ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π°Π΄Π°Ρ‡ ΠΏΠΎ PythonΒ»

Π­Ρ„Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½Ρ‹Π΅ структуры Π΄Π°Π½Π½Ρ‹Ρ… collections

ΠœΠΎΠ΄ΡƒΠ»ΡŒ collections прСдоставляСт высокоуровнСвыС структуры Π΄Π°Π½Π½Ρ‹Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΡŽΡ‚ Π·Π°Π΄Π°Ρ‡ΠΈ, связанныС с ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΉ. НапримСр, defaultdict автоматичСски создаСт значСния ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΊΠ»ΡŽΡ‡Π΅ΠΉ, Ρ‡Ρ‚ΠΎ устраняСт Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ Π² ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°Ρ… ΠΈΠ»ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… условиях. А Π΅Ρ‰Π΅ ΠΎΠ½ ΠΎΡ‡Π΅Π½ΡŒ ΡƒΠ΄ΠΎΠ±Π΅Π½ для Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²ΠΊΠΈ ΠΈΠ»ΠΈ построСния Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Ρ… структур:

from collections import defaultdict

grouped = defaultdict(list)
data = [("Ρ„Ρ€ΡƒΠΊΡ‚Ρ‹", "яблоко"), ("ΠΆΠΈΠ²ΠΎΡ‚Π½ΠΎΠ΅", "кошка"), ("Ρ„Ρ€ΡƒΠΊΡ‚Ρ‹", "Π±Π°Π½Π°Π½"), ("ΠΆΠΈΠ²ΠΎΡ‚Π½ΠΎΠ΅", "собака")]
for key, value in data:
    grouped[key].append(value)
print(grouped)

Π’Ρ‹Π²ΠΎΠ΄:

defaultdict(<class 'list'>, {'Ρ„Ρ€ΡƒΠΊΡ‚Ρ‹': ['яблоко', 'Π±Π°Π½Π°Π½'], 'ΠΆΠΈΠ²ΠΎΡ‚Π½ΠΎΠ΅': ['кошка', 'собака']})

Counter ΡƒΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚ подсчСт:

from collections import Counter

text = "hello world"
char_count = Counter(text)
print(char_count.most_common(3)) 

Π’Ρ‹Π²ΠΎΠ΄:

[('l', 3), ('o', 2), ('h', 1)]

namedtuple ΡƒΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚ созданиС нСизмСняСмых ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² с ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹ΠΌΠΈ полями:

from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
print(p.x, p.y)

Π’Ρ‹Π²ΠΎΠ΄:

3 4

Π£ΠΏΡ€ΠΎΡ‰Π΅Π½ΠΈΠ΅ многопоточности ΠΈ многопроцСссорности

ΠœΠΎΠ΄ΡƒΠ»ΡŒ concurrent.futures прСдоставляСт высокоуровнСвый интСрфСйс для выполнСния Π·Π°Π΄Π°Ρ‡ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ с использованиСм:

  • ThreadPoolExecutor – для Π·Π°Π΄Π°Ρ‡ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π°.
  • ProcessPoolExecutor – для Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ слоТных Π·Π°Π΄Π°Ρ‡, Π½Π°Π³Ρ€ΡƒΠΆΠ°ΡŽΡ‰ΠΈΡ… процСссор.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Π²Π΅Π±-страниц Π² Ρ€Π°Π·Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ°Ρ…

import requests
from concurrent.futures import ThreadPoolExecutor

def fetch_url(url):
    response = requests.get(url)
    return url, response.status_code

urls = ["https://example.com", "https://python.org", "https://proglib.io"]

with ThreadPoolExecutor(max_workers=3) as executor:
    results = executor.map(fetch_url, urls)

for url, status in results:
    print(f"{url}: {status}")

Π’Ρ‹Π²ΠΎΠ΄:

https://example.com: 200
https://python.org: 200
https://proglib.io: 200

Π Π°Π±ΠΎΡ‚Π° с Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмой

ΠœΠΎΠ΄ΡƒΠ»ΡŒ pathlib позволяСт Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с путями ΠΊΠ°ΠΊ с ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ, прСдоставляя ΠΈΠ½Ρ‚ΡƒΠΈΡ‚ΠΈΠ²Π½Ρ‹ΠΉ синтаксис ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄Π΅Π»Π°ΡŽΡ‚ ΠΊΠΎΠ΄ Π»Π°ΠΊΠΎΠ½ΠΈΡ‡Π½Ρ‹ΠΌ ΠΈ понятным. ΠŸΡ€Π΅ΠΈΠΌΡƒΡ‰Π΅ΡΡ‚Π²Π° pathlib ΠΏΠΎ ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с os.path:

  • Π‘ΠΎΠ»Π΅Π΅ простыС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
  • Код Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ Π½Π° всСх ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Ρ… систСмах.
  • Π•ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π» для чтСния, записи, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΏΡƒΡ‚Π΅ΠΉ, ΠΎΠ±Ρ…ΠΎΠ΄Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΉ ΠΈ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Ρ„Π°ΠΉΠ»Π°ΠΌΠΈ.
  • ΠžΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ Π΄Π΅Π»Π°Π΅Ρ‚ ΠΊΠΎΠ΄ Π±ΠΎΠ»Π΅Π΅ структурированным.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: поиск .docx-Ρ„Π°ΠΉΠ»ΠΎΠ² Π²ΠΎ всСх поддирСкториях:

from pathlib import Path
path = Path("C:/Users/Admin/Documents")
for file in path.rglob("*.docx"):
    print(file)

ΠŸΡ€ΠΈ использовании os.path ΠΊΠΎΠ΄ получаСтся Π±ΠΎΠ»Π΅Π΅ Π³Ρ€ΠΎΠΌΠΎΠ·Π΄ΠΊΠΈΠΌ:

import os
path = "C:/Users/Admin/Documents"
for dirpath, dirnames, filenames in os.walk(path):
    for filename in filenames:
        if filename.endswith(".docx"):
            print(os.path.join(dirpath, filename))

Мокинг Π² ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½Ρ‹Ρ… тСстах

ИспользованиС ΠΌΠΎΠΊΠΈΠ½Π³Π° Π² ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½Ρ‹Ρ… тСстах – ΠΌΠΎΡ‰Π½Ρ‹ΠΉ способ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ тСстируСмый ΠΊΠΎΠ΄ ΠΎΡ‚ Π²Π½Π΅ΡˆΠ½ΠΈΡ… зависимостСй (Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ…, Π²Π΅Π±-сСрвисы ΠΈΠ»ΠΈ сторонниС API). Π­Ρ‚ΠΎ ΡƒΠ»ΡƒΡ‡ΡˆΠ°Π΅Ρ‚ ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½ΠΎΡΡ‚ΡŒ, ΡΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ ΠΈ ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΡΠ΅ΠΌΠΎΡΡ‚ΡŒ тСстов, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π΄Π°Π΅Ρ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Ρ‚Π΅ΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ части систСмы, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΅Ρ‰Π΅ Π½Π΅ ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ с внСшними сСрвисами.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€: ΠΌΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ API для получСния курса Π±ΠΈΡ‚ΠΊΠΎΠΈΠ½Π°

import requests
from unittest.mock import patch

def get_bitcoin_price():

    response = requests.get("https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd")
    data = response.json()
    if "bitcoin" not in data:
        raise ValueError("Ошибка получСния Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΡ‚ API")
    return data["bitcoin"]["usd"]

@patch('requests.get')
def test_get_bitcoin_price(mock_get):
    mock_get.return_value.json.return_value = {
        "bitcoin": {
            "usd": 99000  
        }
    }
    
    price = get_bitcoin_price()
    print(f"ВСкущая ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ Π±ΠΈΡ‚ΠΊΠΎΠΈΠ½Π° ${price}.")

test_get_bitcoin_price()

Π’Ρ‹Π²ΠΎΠ΄:

ВСкущая ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ Π±ΠΈΡ‚ΠΊΠΎΠΈΠ½Π° $99000.

ΠŸΠΎΠ΄Π΅Π»ΠΈΡ‚Π΅ΡΡŒ своими Π»ΡŽΠ±ΠΈΠΌΡ‹ΠΌΠΈ Python-ΠΏΡ€ΠΈΡ‘ΠΌΠ°ΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ вошли Π² ΡΡ‚Π°Ρ‚ΡŒΡŽ – ΠΊΠ°ΠΊΠΈΠ΅ Ρ‚Π΅Ρ…Π½ΠΈΠΊΠΈ Π²Ρ‹ считаСтС ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ для ΠΏΡ€ΠΎΡ„Π΅ΡΡΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°?

***

Python ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π²Π΅Π·Π΄Π΅: ΠΎΡ‚ Π°Π½Π°Π»ΠΈΠ·Π° Π΄Π°Π½Π½Ρ‹Ρ… Π΄ΠΎ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π²Π΅Π±-ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. Если Ρ‚Ρ‹ Π·Π°Π΄ΡƒΠΌΡ‹Π²Π°Π΅ΡˆΡŒΡΡ ΠΎ Π²Ρ…ΠΎΠ΄Π΅ Π² IT ΠΈΠ»ΠΈ Ρ…ΠΎΡ‡Π΅ΡˆΡŒ Ρ€Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ свой тСхничСский стСк, ΠΎΠ±Ρ€Π°Ρ‚ΠΈ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Π½ΠΎΠ²Ρ‹ΠΉ курс ΠΏΠΎ основам Python.

ΠšΠ»ΡŽΡ‡Π΅Π²Ρ‹Π΅ особСнности ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹:

  • 32 практичСских ΡƒΡ€ΠΎΠΊΠ° с фокусом Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρ‹
  • Π”Π²Π° ΠΎΠΏΡ‹Ρ‚Π½Ρ‹Ρ… прСподаватСля ΠΈΠ· индустрии: экс-спСциалист ΠœΠ΅Π³Π°Ρ„ΠΎΠ½Π° ΠΈ ΠΎΠ»ΠΈΠΌΠΏΠΈΠ°Π΄Π½Ρ‹ΠΉ Ρ‚Ρ€Π΅Π½Π΅Ρ€
  • Π Π°Π±ΠΎΡ‚Π° с соврСмСнными инструмСнтами: PyCharm, Jupyter Notebook
  • Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ собствСнного ΠΏΠΎΡ€Ρ‚Ρ„ΠΎΠ»ΠΈΠΎ ΠΈΠ· 4 ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ²

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ всё Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠ΅ для старта:

  • ΠžΡ‚ Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ синтаксиса Π΄ΠΎ ООП
  • Π Π°Π±ΠΎΡ‚Π° с API ΠΈ созданиС Π±ΠΎΡ‚ΠΎΠ²
  • ΠŸΠ°Ρ€ΡΠΈΠ½Π³ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Ρ€Π°Π±ΠΎΡ‚Π° с Ρ„Π°ΠΉΠ»Π°ΠΌΠΈ
  • ΠžΡΠ½ΠΎΠ²Ρ‹ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΎΠ² ΠΈ структур Π΄Π°Π½Π½Ρ‹Ρ…

Π€ΠΎΡ€ΠΌΠ°Ρ‚ обучСния Π°Π΄Π°ΠΏΡ‚ΠΈΠ²Π½Ρ‹ΠΉ β€” ΡƒΡ‡ΠΈΡΡŒ Π² своСм Ρ‚Π΅ΠΌΠΏΠ΅ с постоянной ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΉ связью ΠΎΡ‚ ΠΏΡ€Π΅ΠΏΠΎΠ΄Π°Π²Π°Ρ‚Π΅Π»Π΅ΠΉ.

Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•

admin
11 дСкабря 2018

ООП Π½Π° Python: ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ, ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python допускаСт Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ»ΠΎΠ³ΠΈΠΈ, Π½ΠΎ Π² Π΅Π³ΠΎ основС...
admin
28 июня 2018

3 самых Π²Π°ΠΆΠ½Ρ‹Ρ… сфСры примСнСния Python: возмоТности языка

БущСствуСт мноТСство областСй примСнСния Python, Π½ΠΎ Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΎΠ½ особСнно...
admin
13 фСвраля 2017

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python: ΠΎΡ‚ Π½ΠΎΠ²ΠΈΡ‡ΠΊΠ° Π΄ΠΎ профСссионала

Пошаговая инструкция для всСх, ΠΊΡ‚ΠΎ Ρ…ΠΎΡ‡Π΅Ρ‚ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒΒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python...