Практические задания по программированию на языке Python

Раздел: Основы Python -> Задачи разработчика

Задачи Python разработчика: обзор и решения

Как реализовать классическую задачу FizzBuzz?

Основное решение с использованием цикла и условных операторов:


n = 15
for i in range(1, n + 1):
    if i % 3 == 0 and i % 5 == 0:
        print('FizzBuzz')
    elif i % 3 == 0:
        print('Fizz')
    elif i % 5 == 0:
        print('Buzz')
    else:
        print(i)

задачи python разработчика (задачи для python-разработчика)

Этот вариант прост для понимания и работает за линейное время. Порядок проверок важен: сначала проверка на оба условия, иначе числа, кратные 15, будут помечены только как Fizz или Buzz.

Как записать FizzBuzz одной строкой через list comprehension?


result = ['FizzBuzz' if i % 15 == 0 else 'Fizz' if i % 3 == 0 else 'Buzz' if i % 5 == 0 else str(i) for i in range(1, 16)]
print('\n'.join(result))

Подходит для вывода как строки, но менее читаемо.

Как использовать функции высшего порядка?


f = lambda i: 'FizzBuzz' if i % 15 == 0 else 'Fizz' if i % 3 == 0 else 'Buzz' if i % 5 == 0 else str(i)
print('\n'.join(map(f, range(1, 16))))

Выглядит функционально, но сложно для отладки.

Типичная ошибка: неправильный порядок проверок (пропуск проверки на 15). Это приводит к тому, что для 15 выводится 'Fizz' или 'Buzz'. Решение: разместить условие с %15 первым.

Еще одна проблема: забывают преобразовать число в строку при использовании join.

Как проверить, является ли строка палиндромом (с учётом только букв и цифр)?

Основной способ: очистить строку от небуквенно-цифровых символов, привести к нижнему регистру и сравнить с обратной версией.


import re

def is_palindrome(s: str) -> bool:
    cleaned = re.sub(r'[^a-zA-Z0-9]', '', s).lower()
    return cleaned == cleaned[::-1]

print(is_palindrome('A man, a plan, a canal: Panama'))  # True

Этот метод лаконичен и корректен для большинства случаев.

Как обойтись без регулярных выражений?


def is_palindrome_no_re(s: str) -> bool:
    cleaned = ''.join(ch for ch in s if ch.isalnum()).lower()
    return cleaned == cleaned[::-1]

Такой вариант использует isalnum() и генератор, он не зависит от модуля re.

Как проверить с помощью двух указателей (без создания новой строки)?


def is_palindrome_two_pointers(s: str) -> bool:
    left, right = 0, len(s) - 1
    while left < right:
        while left < right and not s[left].isalnum():
            left += 1
        while left < right and not s[right].isalnum():
            right -= 1
        if s[left].lower() != s[right].lower():
            return False
        left += 1
        right -= 1
    return True

Экономит память, не создавая промежуточную строку.

Распространенная ошибка: игнорирование регистра или неверная очистка от символов, не являющихся буквами и цифрами. Например, проверка строки 'RaceCar' вернет False, если не привести к нижнему регистру.

Пустая строка или строка только из пробелов считается палиндромом.

Как вычислить факториал числа без использования встроенной библиотеки?

Итеративный способ с циклом for:


def factorial_iterative(n: int) -> int:
    if n < 0:
        raise ValueError('Факториал не определён для отрицательных чисел')
    result = 1
    for i in range(2, n + 1):
        result *= i
    return result

print(factorial_iterative(5))  # 120

Итерация не нагружает стек и работает для больших значений (пока позволяет память).

Как написать рекурсивную версию?


def factorial_recursive(n: int) -> int:
    if n < 0:
        raise ValueError('Факториал не определён для отрицательных чисел')
    if n <= 1:
        return 1
    return n * factorial_recursive(n - 1)

Просто, но может вызвать RecursionError при n > 1000 (зависит от настроек).

Как использовать functools.reduce?


from functools import reduce

def factorial_reduce(n: int) -> int:
    if n < 0:
        raise ValueError('Факториал не определён')
    return reduce(lambda x, y: x * y, range(1, n + 1), 1)

print(factorial_reduce(6))  # 720

Стиль функционального программирования.

Основная ошибка: не обрабатываются отрицательные числа. Также при рекурсии легко превысить лимит глубины. Решение: использовать итеративный подход или увеличить лимит sys.setrecursionlimit().

Для больших чисел (n > 1000) результат может быть очень большим, но Python справляется с большими целыми числами.

Как прочитать данные из CSV файла и преобразовать их в список словарей?

Использование модуля csv.DictReader:


import csv

with open('data.csv', newline='', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    data = [row for row in reader]

print(data[:2])

Возвращает список словарей, где ключи взяты из первой строки файла.

Как прочитать с помощью csv.reader без заголовков?


with open('data.csv', newline='') as f:
    reader = csv.reader(f)
    header = next(reader)  # первая строка
    data = [dict(zip(header, row)) for row in reader]

Позволяет задать свои ключи.

Как использовать pandas для более сложных операций?


import pandas as pd
df = pd.read_csv('data.csv')
data = df.to_dict('records')

Pandas предоставляет множество возможностей фильтрации и анализа, но требует установки внешней библиотеки.

Проблемы с кодировкой: файл может быть в cp1251 или другой. Решение: указать encoding='cp1251' при открытии.

Пропущенные значения и кавычки: csv.DictReader автоматически обрабатывает кавычки, но если в данных есть запятые внутри полей, нужно убедиться, что файл правильно экранирован.

Пустые строки в конце файла: можно добавить проверку на пустую строку при фильтрации.

Расширенные примеры и нестандартные решения

Генератор чисел Фибоначчи с кешированием (декоратор lru_cache)

Использование декоратора functools.lru_cache позволяет избежать повторных вычислений при рекурсивном подходе.

Пример

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n: int) -> int:
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

# вывод первых 20 чисел
[fib(i) for i in range(20)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]

Декоратор автоматически запоминает результаты для уже вычисленных аргументов, что превращает экспоненциальную рекурсию в линейную.

Чтение большого текстового файла по частям (генератор с yield)

Для обработки файлов, не помещающихся в память, используют чтение фиксированными блоками.

Пример

def read_in_chunks(file_path: str, chunk_size: int = 1024):
    with open(file_path, 'rb') as f:
        while True:
            chunk = f.read(chunk_size)
            if not chunk:
                break
            yield chunk

# пример использования
for chunk in read_in_chunks('large_file.bin', 4096):
    process(chunk)  # вызов пользовательской функции

Генератор не загружает весь файл в память, отдавая данные порциями.

Параллельная обработка списка с помощью multiprocessing.Pool

Ускорение вычислений за счет задействования всех ядер процессора.

Пример

from multiprocessing import Pool
import math

def is_prime(n: int) -> bool:
    if n < 2:
        return False
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True

if __name__ == '__main__':
    numbers = list(range(1, 10001))
    with Pool(processes=4) as pool:
        results = pool.map(is_prime, numbers)
    print(sum(results), 'чисел являются простыми')
1229 чисел являются простыми  # результат может незначительно отличаться

Pool.map распределяет элементы входного списка между рабочими процессами и собирает результаты в исходном порядке.

Создание декоратора для замера времени выполнения функции

Полезно для профилирования кода.

Пример

import time
from functools import wraps

def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        print(f'{func.__name__} выполнена за {end - start:.6f} сек')
        return result
    return wrapper

@timer
def slow_sum(n: int) -> int:
    return sum(range(n))

slow_sum(10_000_000)
slow_sum выполнена за 0.382934 сек
30000000

Декоратор timer позволяет легко добавлять хронометраж к любой функции без изменения её кода.

Задачи для Python-разработчика - comments

En
задачи python разработчика (python)