Block scope in Python

Когда вы кодируете на других языках, вы иногда создаете область видимости блока, например:

statement
...
statement
{
    statement
    ...
    statement
}
statement
...
statement

Одна цель (из многих) - улучшить читаемость кода: показать, что определенные операторы образуют логическую единицу или что определенные локальные переменные используются только в этом блоке.

Есть ли идиоматический способ сделать то же самое в Python?

84
задан gsamaras 17 March 2016 в 09:57
поделиться

1 ответ

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

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

область действия блока Попытки с классами

В течение нескольких моментов я думал, что достиг области действия блока путем прикрепления кода в объявлении класса:

x = 5
class BlockScopeAttempt:
    x = 10
    print(x) # Output: 10
print(x) # Output: 5

, К сожалению, это ломается, когда функция определяется:

x = 5 
class BlockScopeAttempt: 
    x = 10
    print(x) # Output: 10
    def printx2(): 
        print(x) 
    printx2() # Output: 5!!!

That’s, потому что функции, определяемые в классе используют глобальную область видимости. Самое легкое (хотя не единственное) способ зафиксировать это должно явно указать класс:

x = 5 
class BlockScopeAttempt: 
    x = 10
    print(x) # Output: 10
    def printx2(): 
        print(BlockScopeAttempt.x)  # Added class name
    printx2() # Output: 10

Это не настолько изящно, потому что нужно записать функции по-другому в зависимости от того, содержал ли they’re в классе.

Лучшие результаты с модулями Python

Модули очень похожи на статические классы, но модули являются намного более чистыми, по моему опыту. Чтобы сделать то же с модулями, я делаю файл названным my_module.py в текущем рабочем каталоге со следующим содержанием:

x = 10
print(x) # (A)

def printx():
    global x
    print(x) # (B)

Затем в моем основном файле или интерактивный (например, Jupyter) сессия, я делаю

x = 5
import my_module # Output: 10 from (A)
my_module.printx() # Output: 10 from (B)
print(x) # Output: 5

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

, Если Вы работаете с модулями на интерактивной сессии, можно выполнить эти две строки вначале

%load_ext autoreload
%autoreload 2

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

Пакеты для загрузки и фильтрации данных

идея пакетов является небольшим расширением понятия модулей. Пакет является каталогом, содержащим (возможно пробел) __init__.py файл, который выполняется на импорт. К модулям/пакетам в рамках этого каталога можно получить доступ с . синтаксис.

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

В наше время с Python, я определяю пакет, названный my_data, который содержит подмодули, названные load и filter. В filter.py я могу сделать относительный импорт:

from .load import raw_data

, Если я изменяю filter.py, затем autoreload, обнаружит изменения. Это не перезагружает load.py, таким образом, я не должен перезагружать свои данные. Таким образом, я могу моделировать свой код фильтрации в ноутбуке Jupyter, перенести его как функцию и затем вставку сокращения от моего ноутбука непосредственно в [1 118]. Понимание этого коренным образом изменило мой рабочий процесс и преобразовало меня от скептика стороннику “Zen Python. ”

0
ответ дан 24 November 2019 в 08:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: