Skip to content

Latest commit

 

History

History
842 lines (588 loc) · 31.4 KB

File metadata and controls

842 lines (588 loc) · 31.4 KB

Лекция 11. Imports. Standard library. PEP8

Импорты

Лекция: Импортирование в Python

Сегодня мы поговорим о важной теме в Python — импортировании модулей. Это ключевая часть работы с кодом, которая позволяет нам организовывать и переиспользовать код в наших проектах.

В этой части лекции мы затронем:

  1. Ключевые слова from, import, и as.
  2. Абсолютные и относительные импорты.
  3. Роль файлов __init__.py.
  4. Специфичное значение конструкции if __name__ == '__main__':.

Модули и пакеты

Модули

Модуль в Python — это файл, содержащий определения и инструкции Python. Модули позволяют организовывать код в логически связные части, упрощая его поддержку и переиспользование. Каждый модуль имеет свой собственный пространственный контекст, что позволяет избегать конфликтов имен.

Основные концепции:

  1. Модуль как файл:

    • Любой файл с расширением .py является модулем.
    • Имя модуля соответствует имени файла.

    Например, файл math_operations.py является модулем math_operations.

  2. Определения в модуле:

    • Модуль может содержать функции, классы, переменные, а также исполняемый код.
    # math_operations.py
    
    def add(a, b):
        return a + b
    
    def subtract(a, b):
        return a - b
    
    pi = 3.14159
  3. Импортирование модулей:

    • Вы можете импортировать модуль, используя ключевое слово import.
    import math_operations
    
    print(math_operations.add(5, 3))  # Вывод: 8
    print(math_operations.pi)         # Вывод: 3.14159
  4. Использование ключевых слов from и import:

    • Вы можете импортировать конкретные функции или переменные из модуля.
    from math_operations import add, pi
    
    print(add(5, 3))  # Вывод: 8
    print(pi)         # Вывод: 3.14159
  5. Псевдонимы с использованием ключевого слова as:

    • Вы можете использовать псевдонимы для импортированных модулей или их частей.
    import math_operations as mo
    
    print(mo.add(5, 3))  # Вывод: 8

Пакеты в Python

Пакет в Python — это коллекция модулей, организованных в директорию, которая содержит файл __init__.py. Пакеты позволяют создавать иерархию модулей, упрощая организацию больших проектов.

Пример структуры пакета:

project/
    ├── package/
    │   ├── __init__.py
    │   ├── module1.py
    │   └── module2.py
    └── main.py

В файле __init__.py можно инициализировать пакет и упростить импорт модулей (хотя это совершенно не обязательно):

# package/__init__.py
from .module1 import function1
from .module2 import function2

Теперь вы можете импортировать функции напрямую из пакета:

# main.py
from package import function1, function2

function1()
function2()

Важные моменты

  1. Повторное использование кода:

    • Модули позволяют переиспользовать код в разных частях проекта или в других проектах.
  2. Организация кода:

    • Модули и пакеты помогают структурировать проект, делая его более понятным и легким в поддержке.
  3. Разделение пространства имен:

    • Каждый модуль имеет свое собственное пространство имен, что позволяет избегать конфликтов имен.
  4. Публичные и приватные части:

    • В модуле можно указать, какие части должны быть доступны извне, а какие — нет. Для этого используется соглашение об именовании: имена, начинающиеся с одного подчеркивания _, считаются приватными.
    # example.py
    def public_function():
        pass
    
    def _private_function():
        pass

Чуток детальнее

Ключевые слова from, import, и as

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

Ключевое слово import

Ключевое слово import используется для импортирования всего модуля. Когда вы импортируете модуль таким образом, вы можете обращаться к его содержимому, используя точечную нотацию.

Кроме вашего написанного кода, внутри python существуют сотни если не тысячи дополнительных модулей которые можно импортировать.

Какие-то из них используются постоянно, какие-то вы не увидите никогда.

Кроме того, можно установить еще тысячи, если не десятки тысяч готовых модулей, но об этом будет отдельная лекция

Пример:

import math

print(math.sqrt(16))  # Вывод: 4.0

Ключевое слово from

Ключевое слово from используется для импортирования конкретных частей модуля. Это позволяет вам импортировать только те функции, классы или переменные, которые вам нужны.

Пример:

from math import sqrt

print(sqrt(16))  # Вывод: 4.0

Ключевое слово as

Ключевое слово as позволяет вам дать импортированному модулю или его части псевдоним. Это может быть полезно для сокращения длинных имен или разрешения конфликтов имен (например, когда в разных модулях есть функции с одинаковыми названиями).

Пример:

import math as m

print(m.sqrt(16))  # Вывод: 4.0

Или в сочетании с from:

from math import sqrt as square_root

print(square_root(16))  # Вывод: 4.0

Абсолютные и относительные импорты

Абсолютные импорты

Абсолютные импорты — это способ импортирования модулей, используя полный путь к модулю от корневого пакета. Они делают ваш код более читаемым и ясным.

Пример:

Предположим, у нас есть следующая структура каталогов:

project/
    ├── main.py
    ├── package_a/
    │   └── __init__.py
    │   └── foo.py
    └── package_b/
        └── __init__.py
        └── bar.py

В файле foo.py мы можем импортировать функцию из bar.py таким образом:

# module_a/foo.py
from package_b.bar import some_function

В этом примере мы используем абсолютный импорт, указывая полный путь от корня проекта (package_b.bar).

Относительные импорты

Относительные импорты используются для импортирования модулей относительно текущего модуля или пакета. Это удобный способ, когда нужно импортировать модули, находящиеся в том же пакете или соседних пакетах.

Пример:

В файле foo.py, чтобы импортировать модуль bar из того же пакета package_a, мы можем использовать относительный импорт:

# package_a/foo.py
from .bar import some_function

Здесь . означает текущий пакет. Для импорта модуля из родительского пакета используем ..:

# module_a/foo.py
from ..package_b.bar import some_function

3. Роль файлов __init__.py

Файлы __init__.py используются для обозначения директорий как пакетов Python. Эти файлы могут быть пустыми, но их присутствие сигнализирует интерпретатору Python, что директория должна рассматриваться как пакет.

Примеры использования __init__.py:

  • Пустой __init__.py: Простой способ указать, что директория является пакетом.
  • С кодом: Вы можете включить код в __init__.py, чтобы инициализировать пакет, настроить логирование или импортировать часто используемые подмодули:
# module_a/__init__.py
from .foo import FooClass
from .bar import BarClass

Теперь при импорте module_a можно напрямую обращаться к FooClass и BarClass:

from module_a import FooClass, BarClass

4. Специфичное значение конструкции if __name__ == '__main__':

В Python специальная переменная __name__ содержит имя текущего модуля. Когда скрипт запускается как основная программа, __name__ имеет значение '__main__'. Это позволяет писать код, который будет выполняться только в случае, если скрипт запущен напрямую, а не импортирован как модуль.

Пример:

Создадим файл example.py:

# example.py
def main():
    print("Это главный скрипт.")


if __name__ == '__main__':
    main()

Если вы запустите example.py, вы увидите вывод "Это главный скрипт.". Но если вы импортируете этот файл как модуль в другом скрипте:

# another_script.py
import example

Никакой вывод не произойдет, так как main() не будет вызван.

Используем для того что бы отделить между собой основной файл и второстепенные модули

Стандартная библиотека и про некоторые модули

Python — это мощный язык программирования с богатой стандартной библиотекой, включающей множество встроенных модулей. Эти модули предоставляют функции и классы для выполнения широкого круга задач, от работы с системой и файловой системой до математических операций и генерации случайных чисел.

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

Сегодня мы рассмотрим некоторые из наиболее часто используемых встроенных модулей в Python: sys, os, math, random, collections, datetime, и itertools.

sys

Модуль sys предоставляет доступ к некоторым переменным, используемым или поддерживаемым интерпретатором Python, а также к функциям, которые взаимодействуют с ним.

Примеры:

import sys

# Получить аргументы командной строки
print("Аргументы командной строки:", sys.argv)

# Выход из программы
# Примечание: sys.exit(0) завершит выполнение программы, поэтому его обычно не используют в примерах.
# sys.exit(0)

# Версия Python
print("Версия Python:", sys.version)

# Путь поиска модулей
print("Путь поиска модулей:", sys.path)

os

Модуль os предоставляет множество функций для взаимодействия с операционной системой.

Примеры:

import os

# Получить текущую рабочую директорию
current_dir = os.getcwd()
print("Текущая рабочая директория:", current_dir)

# Изменить текущую рабочую директорию
new_dir = '/tmp'
os.chdir(new_dir)
print("Рабочая директория изменена на:", os.getcwd())

# Список файлов и директорий в текущей директории
files = os.listdir('.')
print("Файлы и директории в текущей директории:", files)

# Создание новой директории
new_dir_name = 'new_dir'
if not os.path.exists(new_dir_name):
    os.mkdir(new_dir_name)
    print("Создана директория:", new_dir_name)

# Удаление файла
file_name = 'test.txt'
if os.path.exists(file_name):
    os.remove(file_name)
    print("Файл удален:", file_name)
else:
    print("Файл не существует:", file_name)

math

Модуль math предоставляет доступ к математическим функциям, определенным в стандарте C.

Примеры:

import math

# Вычислить квадратный корень
sqrt_value = math.sqrt(16)
print("Квадратный корень из 16:", sqrt_value)

# Вычислить синус угла в радианах
sin_value = math.sin(math.pi / 2)
print("Синус угла pi/2 радиан:", sin_value)

# Вычислить логарифм
log_value = math.log(10)
print("Натуральный логарифм 10:", log_value)

# Константы π и e
print("Константа π:", math.pi)
print("Константа e:", math.e)

# Округление вниз и вверх
floor_value = math.floor(3.7)
ceil_value = math.ceil(3.3)
print("Округление 3.7 вниз:", floor_value)
print("Округление 3.3 вверх:", ceil_value)

random

Модуль random реализует генераторы псевдослучайных чисел для различных распределений.

Примеры:

import random

# Случайное число от 0 до 1
random_value = random.random()
print("Случайное число от 0 до 1:", random_value)

# Случайное целое число в диапазоне
random_int = random.randint(1, 10)
print("Случайное целое число от 1 до 10:", random_int)

# Случайный выбор из списка
choices = ['apple', 'banana', 'cherry']
random_choice = random.choice(choices)
print("Случайный выбор из списка:", random_choice)

# Перемешивание списка
my_list = [1, 2, 3, 4, 5]
random.shuffle(my_list)
print("Перемешанный список:", my_list)

# Случайное вещественное число в диапазоне
random_float = random.uniform(1.0, 10.0)
print("Случайное вещественное число от 1.0 до 10.0:", random_float)

collections

Модуль collections реализует специализированные контейнерные типы данных.

Примеры:

from collections import Counter, defaultdict, deque, namedtuple

# Counter
text = "abracadabra"
counter = Counter(text)
print("Подсчет символов в строке 'abracadabra':", counter)

# defaultdict
def_dict = defaultdict(int)
def_dict['apple'] += 1
print("defaultdict с начальным значением int:", def_dict)

# deque
queue = deque([1, 2, 3])
queue.appendleft(0)
queue.append(4)
print("Очередь deque после добавления элементов:", queue)

# namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print("Координаты точки:", p.x, p.y)

datetime

Модуль datetime предоставляет классы для работы с датой и временем.

Примеры:

from datetime import date, datetime, timedelta

# Текущая дата
today = date.today()
print("Текущая дата:", today)

# Текущее время
now = datetime.now()
print("Текущее время:", now)

# Вычисление разницы во времени
delta = timedelta(days=7)
next_week = today + delta
print("Дата через неделю:", next_week)

# Форматирование даты
formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
print("Форматированная дата и время:", formatted_date)

# Парсинг даты из строки
date_str = "2024-07-23"
parsed_date = datetime.strptime(date_str, "%Y-%m-%d")
print("Парсинг даты из строки:", parsed_date)

itertools

Модуль itertools предоставляет функции для создания итераторов для эффективного цикла.

Примеры:

import itertools

# Бесконечный счетчик
print("Бесконечный счетчик с началом с 10 и шагом 2:")
for i in itertools.count(10, 2):
    if i > 20:
        break
    print(i, end=' ')
print()

# Повторение элемента
counter = itertools.cycle(['A', 'B', 'C'])
print("Повторение элементов 'A', 'B', 'C':")
for _ in range(10):
    print(next(counter), end=' ')
print()

# Комбинации
combinations = list(itertools.combinations('ABCD', 2))
print("Комбинации из 2 элементов строки 'ABCD':", combinations)

# Переключение значений
toggle = itertools.cycle([True, False])
print("Переключение значений True и False:")
for _ in range(6):
    print(next(toggle), end=' ')
print()

Про docstring и комментарии

Комментарии и строковые литералы документации (docstrings) являются важными инструментами для написания чистого и понятного кода. Комментарии помогают другим разработчикам (и вам самим в будущем) понять, что делает конкретный фрагмент кода, а docstrings служат для создания документации, объясняющей, как пользоваться функциями, классами и модулями.

Комментарии в Python

Комментарии в Python начинаются с символа # и продолжаются до конца строки. Python интерпретирует эти строки как комментарии и игнорирует их при выполнении кода.

Пример использования комментариев:

# Это однострочный комментарий
x = 5  # Это комментарий после кода


# Следующий код вычисляет факториал числа
def factorial(n):
    # Инициализируем результат
    result = 1
    # Перебираем все числа от 1 до n
    for i in range(1, n + 1):
        result *= i
    return result

Комментарии помогают объяснить сложную логику, описать алгоритмы или просто напомнить о важных вещах.

Многострочные комментарии

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

Пример многострочных комментариев:

# Это многострочный комментарий.
# Он используется для объяснения большого блока кода
# или сложного алгоритма.

x = 10
y = 20
z = x + y

Строковые литералы документации (docstrings)

Docstrings - это строки, используемые для документирования модулей, классов, методов и функций. В отличие от обычных комментариев, docstrings можно получить программно через атрибут __doc__.

Пример использования docstring:

def add(a: int, b: int) -> int:
    """
    Возвращает сумму двух чисел.

    Аргументы:
    a -- первое число
    b -- второе число

    Возвращает:
    Сумма аргументов a и b.
    """
    return a + b


# Получение docstring
print(add.__doc__)

Этот docstring объясняет, что делает функция add, какие параметры она принимает и что возвращает.

Docstrings для классов и модулей

Docstrings также используются для документирования классов и модулей.

Пример docstring для класса:

class Dog:
    """
    Класс для представления собаки.

    Атрибуты:
    name (str) -- имя собаки
    age (int) -- возраст собаки

    Методы:
    bark() -- заставляет собаку лаять
    """

    def __init__(self, name: str, age: int):
        """
        Инициализирует объект Dog с именем и возрастом.

        Аргументы:
        name (str) -- имя собаки
        age (int) -- возраст собаки
        """
        self.name = name
        self.age = age

    def bark(self) -> str:
        """Заставляет собаку лаять."""
        return "Woof!"

Пример docstring для модуля:

"""
Этот модуль предоставляет функции для работы с геометрическими фигурами.

Функции:
area_of_circle(radius) -- возвращает площадь круга с заданным радиусом
perimeter_of_square(side) -- возвращает периметр квадрата с заданной стороной
"""


def area_of_circle(radius: float) -> float:
    """Возвращает площадь круга с заданным радиусом."""
    from math import pi
    return pi * radius ** 2


def perimeter_of_square(side: float) -> float:
    """Возвращает периметр квадрата с заданной стороной."""
    return 4 * side

Форматирование docstring

Существуют различные соглашения по форматированию docstring, включая стандарты Google, NumPy/SciPy и reStructuredText ( reST). Важно выбрать один стандарт и придерживаться его во всем проекте.

Пример docstring в стиле Google:

def multiply(a: int | float, b: int | float) -> int | float:
    """
    Умножает два числа.

    Args:
        a (int, float): Первое число.
        b (int, float): Второе число.

    Returns:
        int, float: Произведение аргументов a и b.
    """
    return a * b

Docstring как и типизации в современном мире считаются обязательным стандартом написания кода, и я ожидаю от вас использования их во всех домашках и модулях!

PEP8 (Python Enhancement Proposal 8) – это руководство по стилю написания кода на Python. Соблюдение этого стандарта помогает разработчикам создавать код, который легко читать и поддерживать. В этой лекции мы рассмотрим основные аспекты PEP8, включая правила именования переменных, использование пробелов, составные инструкции, тернарный оператор и отступы между функциями и классами.

Именование переменных

Правильное именование

  1. Переменные и функции:

    • Используйте стиль snake_case (слова разделяются нижним подчеркиванием).
    • Примеры:
      user_name = "John"
      calculate_total()
  2. Классы:

    • Используйте стиль CamelCase (каждое слово начинается с заглавной буквы).
    • Примеры:
      class UserProfile:
          pass

Неправильное именование

  • Избегайте использования стиля camelCase для функций и переменных.
  • Избегайте слишком коротких или слишком длинных имен.
  • Избегайте имен, состоящих из одного символа (например, x, y), если только это не циклические переменные или индексы.

Использование пробелов

Пробелы вокруг операторов

  • Добавляйте пробелы вокруг операторов присваивания (=), арифметических операторов (+, -, *, / и т.д.), а также вокруг операторов сравнения (==, !=, <, > и т.д.).
    a = b + c
    if a == b:
        pass

Пробелы внутри скобок

  • Не добавляйте пробелы внутри круглых, квадратных или фигурных скобок.
    my_list = [1, 2, 3]
    function_call(a, b)

Пробелы перед запятыми и после запятых

  • Не добавляйте пробелы перед запятыми.
  • Добавляйте пробелы после запятых.
    my_tuple = (1, 2, 3)

Составные инструкции

Избегайте составных инструкций, когда несколько операторов записаны в одной строке.

Неправильно

import os;import sys

Правильно

import os
import sys

Тернарный оператор

Тернарный оператор в Python используется для написания кратких условий. Он позволяет сократить код, записывая условие и результат в одной строке.

Пример использования

result = x if condition else y

Пример

is_even = True if number % 2 == 0 else False

Отступы между функциями и классами

Отступы между функциями и классами способствуют лучшей читаемости кода и разделению логических блоков.

Правила

  1. Отступы между методами внутри класса:

    • Используйте один пустой ряд.
    • Пример:
      class MyClass:
          def method_one(self):
              pass
      
          def method_two(self):
              pass
  2. Отступы между классами и функциями на верхнем уровне:

    • Используйте два пустых ряда.
    • Пример:
      class FirstClass:
          pass
      
      
      class SecondClass:
          pass
      
      
      def my_function():
          pass

В качестве домашки нужно ваш модуль разбить на небольшие логические куски.

Предполагаемая структура:

main.py - файл через который происходит запуск основной логики files.py - файл куда надо переместить всю работу с файлами utils.py - файл со всеми полезными функциями