Определяющие аспекты функций

PythonPythonBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

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

Кроме того, вы будете использовать подсказки типов (type hints), чтобы повысить читаемость и безопасность кода, что является важным аспектом написания высококачественного кода на Python.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/BasicConceptsGroup(["Basic Concepts"]) python(("Python")) -.-> python/PythonStandardLibraryGroup(["Python Standard Library"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ObjectOrientedProgrammingGroup(["Object-Oriented Programming"]) python(("Python")) -.-> python/FileHandlingGroup(["File Handling"]) python/BasicConceptsGroup -.-> python/variables_data_types("Variables and Data Types") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/arguments_return("Arguments and Return Values") python/FunctionsGroup -.-> python/default_arguments("Default Arguments") python/ObjectOrientedProgrammingGroup -.-> python/classes_objects("Classes and Objects") python/FileHandlingGroup -.-> python/file_opening_closing("Opening and Closing Files") python/FileHandlingGroup -.-> python/file_reading_writing("Reading and Writing Files") python/FileHandlingGroup -.-> python/file_operations("File Operations") python/PythonStandardLibraryGroup -.-> python/data_collections("Data Collections") subgraph Lab Skills python/variables_data_types -.-> lab-132503{{"Определяющие аспекты функций"}} python/function_definition -.-> lab-132503{{"Определяющие аспекты функций"}} python/arguments_return -.-> lab-132503{{"Определяющие аспекты функций"}} python/default_arguments -.-> lab-132503{{"Определяющие аспекты функций"}} python/classes_objects -.-> lab-132503{{"Определяющие аспекты функций"}} python/file_opening_closing -.-> lab-132503{{"Определяющие аспекты функций"}} python/file_reading_writing -.-> lab-132503{{"Определяющие аспекты функций"}} python/file_operations -.-> lab-132503{{"Определяющие аспекты функций"}} python/data_collections -.-> lab-132503{{"Определяющие аспекты функций"}} end

Понимание контекста

В предыдущих упражнениях вы, возможно, встречали код, который считывает CSV-файлы и сохраняет данные в различных структурах данных. Цель этого кода - взять необработанные текстовые данные из CSV-файла и преобразовать их в более полезные объекты Python, такие как словари или экземпляры классов. Это преобразование является важным, так как оно позволяет нам работать с данными более структурированным и осмысленным образом в наших Python-программах.

Типичная схема чтения CSV-файлов часто имеет определенную структуру. Вот пример функции, которая считывает CSV-файл и преобразует каждую строку в словарь:

import csv

def read_csv_as_dicts(filename, types):
    records = []
    with open(filename) as file:
        rows = csv.reader(file)
        headers = next(rows)
        for row in rows:
            record = { name: func(val)
                       for name, func, val in zip(headers, types, row) }
            records.append(record)
    return records

Разберем, как работает эта функция. Во - первых, она импортирует модуль csv, который предоставляет функциональность для работы с CSV-файлами в Python. Функция принимает два параметра: filename - имя CSV-файла для чтения, и types - список функций, используемых для преобразования данных в каждой колонке в соответствующий тип данных.

Внутри функции инициализируется пустой список records для хранения словарей, представляющих каждую строку CSV-файла. Затем файл открывается с использованием оператора with, который гарантирует, что файл будет правильно закрыт после выполнения блока кода. Функция csv.reader используется для создания итератора, который считывает каждую строку CSV-файла. Первая строка считается заголовками, поэтому она извлекается с помощью функции next.

Далее функция проходит по оставшимся строкам в CSV-файле. Для каждой строки создается словарь с использованием включения словаря. Ключами словаря являются заголовки колонок, а значениями - результат применения соответствующей функции преобразования типа из списка types к значению в строке. Наконец, словарь добавляется в список records, и функция возвращает список словарей.

Теперь рассмотрим похожую функцию, которая считывает данные из CSV-файла в экземпляры класса:

def read_csv_as_instances(filename, cls):
    records = []
    with open(filename) as file:
        rows = csv.reader(file)
        headers = next(rows)
        for row in rows:
            record = cls.from_row(row)
            records.append(record)
    return records

Эта функция похожа на предыдущую, но вместо создания словарей она создает экземпляры класса. Функция принимает два параметра: filename - имя CSV-файла для чтения, и cls - класс, экземпляры которого будут созданы.

Внутри функции используется схожая структура, как в предыдущей функции. Инициализируется пустой список records для хранения экземпляров класса. Затем файл открывается, считываются заголовки и проходит по оставшимся строкам. Для каждой строки вызывается метод from_row класса cls для создания экземпляра класса с использованием данных из строки. Экземпляр затем добавляется в список records, и функция возвращает список экземпляров.

В этом практическом занятии (лабораторной работе) мы рефакторим эти функции, чтобы сделать их более гибкими и надежными. Мы также рассмотрим систему подсказок типов (type hinting) Python, которая позволяет нам указывать ожидаемые типы параметров и возвращаемых значений наших функций. Это может сделать наш код более читаемым и легким для понимания, особенно для других разработчиков, которые могут работать с нашим кодом.

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

Создание базовых функций для чтения CSV-файлов

Начнем с создания файла reader.py с двумя базовыми функциями для чтения данных из CSV-файлов. Эти функции помогут нам обрабатывать CSV-файлы различными способами, например, преобразовывать данные в словари или экземпляры классов.

Сначала нам нужно понять, что такое CSV-файл. CSV расшифровывается как Comma-Separated Values (значения, разделенные запятыми). Это простой формат файла, используемый для хранения табличных данных, где каждая строка представляет собой строку таблицы, а значения в каждой строке разделены запятыми.

Теперь создадим файл reader.py. Следуйте этим шагам:

  1. Откройте текстовый редактор кода и создайте новый файл с именем reader.py в директории /home/labex/project. Именно здесь мы напишем наши функции для чтения данных из CSV-файлов.

  2. Добавьте следующий код в файл reader.py:

## reader.py

import csv

def read_csv_as_dicts(filename, types):
    '''
    Read CSV data into a list of dictionaries with optional type conversion

    Args:
        filename: Path to the CSV file
        types: List of type conversion functions for each column

    Returns:
        List of dictionaries with data from the CSV file
    '''
    records = []
    with open(filename) as file:
        rows = csv.reader(file)
        headers = next(rows)
        for row in rows:
            record = { name: func(val)
                       for name, func, val in zip(headers, types, row) }
            records.append(record)
    return records

def read_csv_as_instances(filename, cls):
    '''
    Read CSV data into a list of class instances

    Args:
        filename: Path to the CSV file
        cls: Class to create instances from

    Returns:
        List of class instances with data from the CSV file
    '''
    records = []
    with open(filename) as file:
        rows = csv.reader(file)
        headers = next(rows)
        for row in rows:
            record = cls.from_row(row)
            records.append(record)
    return records

В функции read_csv_as_dicts мы сначала открываем CSV-файл с помощью функции open. Затем используем csv.reader для чтения файла построчно. Строка next(rows) читает первую строку файла, которая обычно содержит заголовки. После этого мы проходим по оставшимся строкам. Для каждой строки создаем словарь, где ключами являются заголовки, а значениями - соответствующие значения в строке с возможным преобразованием типов с использованием списка types.

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

  1. Протестируем эти функции, чтобы убедиться, что они работают правильно. Создайте новый файл с именем test_reader.py с следующим кодом:
## test_reader.py

import reader
import stock

## Test reading CSV as dictionaries
portfolio_dicts = reader.read_csv_as_dicts('portfolio.csv', [str, int, float])
print("First portfolio item as dictionary:", portfolio_dicts[0])
print("Total items:", len(portfolio_dicts))

## Test reading CSV as class instances
portfolio_instances = reader.read_csv_as_instances('portfolio.csv', stock.Stock)
print("\nFirst portfolio item as Stock instance:", portfolio_instances[0])
print("Total items:", len(portfolio_instances))

В файле test_reader.py мы импортируем модуль reader, который мы только что создали, и модуль stock. Затем тестируем две функции, вызывая их с использованием образцового CSV-файла с именем portfolio.csv. Мы выводим первый элемент и общее количество элементов в портфеле, чтобы убедиться, что функции работают как ожидается.

  1. Запустите тестовый скрипт из терминала:
python test_reader.py

Вывод должен быть похож на следующий:

First portfolio item as dictionary: {'name': 'AA', 'shares': 100, 'price': 32.2}
Total items: 7

First portfolio item as Stock instance: Stock('AA', 100, 32.2)
Total items: 7

Это подтверждает, что наши две функции работают правильно. Первая функция преобразует данные из CSV-файла в список словарей с правильным преобразованием типов, а вторая функция создает экземпляры класса с использованием статического метода на предоставленном классе.

На следующем шаге мы рефакторим эти функции, чтобы сделать их более гибкими, разрешив им работать с любым итерируемым источником данных, а не только с именами файлов.

✨ Проверить решение и практиковаться

Сделать функции более гибкими

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

Давайте рефакторинг нашего кода, чтобы обеспечить такую гибкость:

  1. Откройте файл reader.py. Мы собираемся изменить его, добавив несколько новых функций. Эти новые функции позволят нашему коду работать с разными типами итерируемых объектов. Вот код, который вам нужно добавить:
## reader.py

import csv

def csv_as_dicts(lines, types):
    '''
    Parse CSV data from an iterable into a list of dictionaries

    Args:
        lines: An iterable producing CSV lines
        types: List of type conversion functions for each column

    Returns:
        List of dictionaries with data from the CSV lines
    '''
    records = []
    rows = csv.reader(lines)
    headers = next(rows)
    for row in rows:
        record = { name: func(val)
                  for name, func, val in zip(headers, types, row) }
        records.append(record)
    return records

def csv_as_instances(lines, cls):
    '''
    Parse CSV data from an iterable into a list of class instances

    Args:
        lines: An iterable producing CSV lines
        cls: Class to create instances from

    Returns:
        List of class instances with data from the CSV lines
    '''
    records = []
    rows = csv.reader(lines)
    headers = next(rows)
    for row in rows:
        record = cls.from_row(row)
        records.append(record)
    return records

def read_csv_as_dicts(filename, types):
    '''
    Read CSV data into a list of dictionaries with optional type conversion

    Args:
        filename: Path to the CSV file
        types: List of type conversion functions for each column

    Returns:
        List of dictionaries with data from the CSV file
    '''
    with open(filename) as file:
        return csv_as_dicts(file, types)

def read_csv_as_instances(filename, cls):
    '''
    Read CSV data into a list of class instances

    Args:
        filename: Path to the CSV file
        cls: Class to create instances from

    Returns:
        List of class instances with data from the CSV file
    '''
    with open(filename) as file:
        return csv_as_instances(file, cls)

Давайте рассмотрим более подробно, как мы рефакторинг кода:

  1. Мы создали две более общие функции, csv_as_dicts() и csv_as_instances(). Эти функции предназначены для работы с любым итерируемым объектом, который генерирует строки CSV. Это означает, что они могут обрабатывать различные типы источников входных данных, а не только файлы, указанные по имени файла.

  2. Мы перереализовали read_csv_as_dicts() и read_csv_as_instances() так, чтобы они использовали эти новые функции. Таким образом, исходная функциональность чтения из файла по имени файла по-прежнему доступна, но теперь она основана на более гибких функциях.

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

  4. Теперь давайте протестируем эти новые функции. Создайте файл с именем test_reader_flexibility.py и добавьте в него следующий код. Этот код протестирует новые функции с разными типами источников входных данных:

## test_reader_flexibility.py

import reader
import stock
import gzip

## Test opening a regular file
with open('portfolio.csv') as file:
    portfolio = reader.csv_as_dicts(file, [str, int, float])
    print("First item from open file:", portfolio[0])

## Test opening a gzipped file
with gzip.open('portfolio.csv.gz', 'rt') as file:  ## 'rt' means read text
    portfolio = reader.csv_as_instances(file, stock.Stock)
    print("\nFirst item from gzipped file:", portfolio[0])

## Test backward compatibility
portfolio = reader.read_csv_as_dicts('portfolio.csv', [str, int, float])
print("\nFirst item using backward compatible function:", portfolio[0])
  1. После создания тестового файла нам нужно запустить тестовый скрипт из терминала. Откройте терминал и перейдите в директорию, где находится файл test_reader_flexibility.py. Затем выполните следующую команду:
python test_reader_flexibility.py

Вывод должен быть похож на следующий:

First item from open file: {'name': 'AA', 'shares': 100, 'price': 32.2}

First item from gzipped file: Stock('AA', 100, 32.2)

First item using backward compatible function: {'name': 'AA', 'shares': 100, 'price': 32.2}

Этот вывод подтверждает, что наши функции теперь работают с разными типами источников входных данных, сохраняя при этом обратную совместимость. Рефакторинг функции могут обрабатывать данные из:

  • Обычных файлов, открытых с помощью open()
  • Сжатых файлов, открытых с помощью gzip.open()
  • Любых других итерируемых объектов, которые генерируют строки текста

Это делает наш код гораздо более гибким и легким в использовании в различных сценариях.

✨ Проверить решение и практиковаться

Обработка CSV-файлов без заголовков

В мире обработки данных не все CSV-файлы имеют заголовки в первой строке. Заголовки - это имена, присвоенные каждой колонке в CSV-файле, которые помогают нам понять, какого рода данные содержит каждая колонка. Когда в CSV-файле отсутствуют заголовки, нам нужно уметь правильно с ним работать. В этом разделе мы модифицируем наши функции, чтобы позволить вызывающему коду вручную задавать заголовки, так что мы сможем работать как с CSV-файлами с заголовками, так и без них.

  1. Откройте файл reader.py и обновите его, добавив обработку заголовков:
## reader.py

import csv

def csv_as_dicts(lines, types, headers=None):
    '''
    Parse CSV data from an iterable into a list of dictionaries

    Args:
        lines: An iterable producing CSV lines
        types: List of type conversion functions for each column
        headers: Optional list of column names. If None, first row is used as headers

    Returns:
        List of dictionaries with data from the CSV lines
    '''
    records = []
    rows = csv.reader(lines)

    if headers is None:
        ## Use the first row as headers if none provided
        headers = next(rows)

    for row in rows:
        record = { name: func(val)
                  for name, func, val in zip(headers, types, row) }
        records.append(record)
    return records

def csv_as_instances(lines, cls, headers=None):
    '''
    Parse CSV data from an iterable into a list of class instances

    Args:
        lines: An iterable producing CSV lines
        cls: Class to create instances from
        headers: Optional list of column names. If None, first row is used as headers

    Returns:
        List of class instances with data from the CSV lines
    '''
    records = []
    rows = csv.reader(lines)

    if headers is None:
        ## Skip the first row if no headers provided
        next(rows)

    for row in rows:
        record = cls.from_row(row)
        records.append(record)
    return records

def read_csv_as_dicts(filename, types, headers=None):
    '''
    Read CSV data into a list of dictionaries with optional type conversion

    Args:
        filename: Path to the CSV file
        types: List of type conversion functions for each column
        headers: Optional list of column names. If None, first row is used as headers

    Returns:
        List of dictionaries with data from the CSV file
    '''
    with open(filename) as file:
        return csv_as_dicts(file, types, headers)

def read_csv_as_instances(filename, cls, headers=None):
    '''
    Read CSV data into a list of class instances

    Args:
        filename: Path to the CSV file
        cls: Class to create instances from
        headers: Optional list of column names. If None, first row is used as headers

    Returns:
        List of class instances with data from the CSV file
    '''
    with open(filename) as file:
        return csv_as_instances(file, cls, headers)

Понять ключевые изменения, которые мы внесли в эти функции:

  1. Мы добавили параметр headers во все функции и установили его значение по умолчанию равным None. Это означает, что если вызывающий код не предоставит заголовки, функции будут использовать поведение по умолчанию.

  2. В функции csv_as_dicts мы используем первую строку как заголовки только в том случае, если параметр headers равен None. Это позволяет нам автоматически обрабатывать файлы с заголовками.

  3. В функции csv_as_instances мы пропускаем первую строку только в том случае, если параметр headers равен None. Это связано с тем, что если мы предоставляем свои собственные заголовки, первая строка файла содержит реальные данные, а не заголовки.

  4. Протестируем эти изменения на файле без заголовков. Создайте файл с именем test_headers.py:

## test_headers.py

import reader
import stock

## Define column names for the file without headers
column_names = ['name', 'shares', 'price']

## Test reading a file without headers
portfolio = reader.read_csv_as_dicts('portfolio_noheader.csv',
                                     [str, int, float],
                                     headers=column_names)
print("First item from file without headers:", portfolio[0])
print("Total items:", len(portfolio))

## Test reading the same file as instances
portfolio = reader.read_csv_as_instances('portfolio_noheader.csv',
                                        stock.Stock,
                                        headers=column_names)
print("\nFirst item as Stock instance:", portfolio[0])
print("Total items:", len(portfolio))

## Verify that original functionality still works
portfolio = reader.read_csv_as_dicts('portfolio.csv', [str, int, float])
print("\nFirst item from file with headers:", portfolio[0])

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

  1. Запустите тестовый скрипт из терминала:
python test_headers.py

Вывод должен быть похож на следующий:

First item from file without headers: {'name': 'AA', 'shares': 100, 'price': 32.2}
Total items: 7

First item as Stock instance: Stock('AA', 100, 32.2)
Total items: 7

First item from file with headers: {'name': 'AA', 'shares': 100, 'price': 32.2}

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

Благодаря этой модификации наши функции для чтения CSV-файлов стали более универсальными и могут обрабатывать более широкий спектр форматов файлов. Это важный шаг в направлении создания более надежного и полезного кода в различных сценариях.

Добавление подсказок по типам

В Python 3.5 и более поздних версиях поддерживаются подсказки по типам (type hints). Подсказки по типам - это способ указать ожидаемые типы данных переменных, параметров функций и возвращаемых значений в вашем коде. Они не влияют на то, как код выполняется, но делают код более читаемым и могут помочь обнаружить определенные типы ошибок до того, как код будет фактически запущен. Теперь давайте добавим подсказки по типам в наши функции для чтения CSV-файлов.

  1. Откройте файл reader.py и обновите его, добавив подсказки по типам:
## reader.py

import csv
from typing import List, Callable, Dict, Any, Type, Optional, TextIO, Iterator, TypeVar

## Define a generic type for the class parameter
T = TypeVar('T')

def csv_as_dicts(lines: Iterator[str],
                types: List[Callable[[str], Any]],
                headers: Optional[List[str]] = None) -> List[Dict[str, Any]]:
    '''
    Parse CSV data from an iterable into a list of dictionaries

    Args:
        lines: An iterable producing CSV lines
        types: List of type conversion functions for each column
        headers: Optional list of column names. If None, first row is used as headers

    Returns:
        List of dictionaries with data from the CSV lines
    '''
    records: List[Dict[str, Any]] = []
    rows = csv.reader(lines)

    if headers is None:
        ## Use the first row as headers if none provided
        headers = next(rows)

    for row in rows:
        record = { name: func(val)
                  for name, func, val in zip(headers, types, row) }
        records.append(record)
    return records

def csv_as_instances(lines: Iterator[str],
                    cls: Type[T],
                    headers: Optional[List[str]] = None) -> List[T]:
    '''
    Parse CSV data from an iterable into a list of class instances

    Args:
        lines: An iterable producing CSV lines
        cls: Class to create instances from
        headers: Optional list of column names. If None, first row is used as headers

    Returns:
        List of class instances with data from the CSV lines
    '''
    records: List[T] = []
    rows = csv.reader(lines)

    if headers is None:
        ## Skip the first row if no headers provided
        next(rows)

    for row in rows:
        record = cls.from_row(row)
        records.append(record)
    return records

def read_csv_as_dicts(filename: str,
                     types: List[Callable[[str], Any]],
                     headers: Optional[List[str]] = None) -> List[Dict[str, Any]]:
    '''
    Read CSV data into a list of dictionaries with optional type conversion

    Args:
        filename: Path to the CSV file
        types: List of type conversion functions for each column
        headers: Optional list of column names. If None, first row is used as headers

    Returns:
        List of dictionaries with data from the CSV file
    '''
    with open(filename) as file:
        return csv_as_dicts(file, types, headers)

def read_csv_as_instances(filename: str,
                         cls: Type[T],
                         headers: Optional[List[str]] = None) -> List[T]:
    '''
    Read CSV data into a list of class instances

    Args:
        filename: Path to the CSV file
        cls: Class to create instances from
        headers: Optional list of column names. If None, first row is used as headers

    Returns:
        List of class instances with data from the CSV file
    '''
    with open(filename) as file:
        return csv_as_instances(file, cls, headers)

Понять ключевые изменения, которые мы внесли в код:

  1. Мы импортировали типы из модуля typing. Этот модуль предоставляет набор типов, которые мы можем использовать для определения подсказок по типам. Например, List, Dict и Optional - это типы из этого модуля.

  2. Мы добавили обобщенную переменную типа T для представления типа класса. Обобщенная переменная типа позволяет нам писать функции, которые могут работать с разными типами в типобезопасном режиме.

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

  4. Мы использовали соответствующие типы контейнеров, такие как List, Dict и Optional. List представляет список, Dict представляет словарь, а Optional указывает, что параметр может иметь определенный тип или быть None.

  5. Мы использовали Callable для функций преобразования типов. Callable используется для указания, что параметр - это функция, которую можно вызвать.

  6. Мы использовали обобщенный тип T для указания, что csv_as_instances возвращает список экземпляров переданного класса. Это помогает IDE и другим инструментам понять тип возвращаемых объектов.

  7. Теперь давайте создадим простой тестовый файл, чтобы убедиться, что все по-прежнему работает правильно:

## test_types.py

import reader
import stock

## The functions should work exactly as before
portfolio = reader.read_csv_as_dicts('portfolio.csv', [str, int, float])
print("First item:", portfolio[0])

## But now we have better type checking and IDE support
stock_portfolio = reader.read_csv_as_instances('portfolio.csv', stock.Stock)
print("\nFirst stock:", stock_portfolio[0])

## We can see that stock_portfolio is a list of Stock objects
## This helps IDEs provide better code completion
first_stock = stock_portfolio[0]
print(f"\nName: {first_stock.name}")
print(f"Shares: {first_stock.shares}")
print(f"Price: {first_stock.price}")
print(f"Value: {first_stock.shares * first_stock.price}")
  1. Запустите тестовый скрипт из терминала:
python test_types.py

Вывод должен быть похож на следующий:

First item: {'name': 'AA', 'shares': 100, 'price': 32.2}

First stock: Stock('AA', 100, 32.2)

Name: AA
Shares: 100
Price: 32.2
Value: 3220.0

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

  1. Они обеспечивают лучшую поддержку IDE с автодополнением кода. Когда вы используете IDE, такое как PyCharm или VS Code, оно может использовать подсказки по типам, чтобы предложить правильные методы и атрибуты для ваших переменных.
  2. Они предоставляют более ясную документацию о ожидаемых типах параметров и возвращаемых значений. Просто посмотрев на определение функции, вы можете понять, какие типы аргументов она ожидает и какой тип значения возвращает.
  3. Они позволяют использовать статические анализаторы типов, такие как mypy, чтобы обнаружить ошибки на ранней стадии. Статические анализаторы типов анализируют ваш код без его запуска и могут найти ошибки, связанные с типами, до того, как вы запустите код.
  4. Они улучшают читаемость и поддерживаемость кода. Когда вы или другие разработчики вернетесь к коду позже, будет легче понять, что код делает.

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

Примечание: Подсказки по типам в Python являются необязательными, но они все чаще используются в профессиональном коде. Библиотеки, такие как те, что есть в стандартной библиотеке Python, и многие популярные сторонние пакеты теперь включают обширные подсказки по типам.

Резюме

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

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