Змеиные глаза (серия 2 частей)
Один из моих домашних питомцев берет концепции с других языков и «переводит» их на Python. Не потому, что он делает хороший код, а потому, что это вызов, и это делает меня счастливым.
На этот раз я пошел после двух простых концепций – вложенных кодовых блоков и iife. Оба служат сходными целями, и оба отсутствуют на Python.
В C ++ блоки часто используются для ограничения срока службы объектов и удержать их от нашего пути, когда мы закончили с ними. В Python жизнь, как правило, меньше вызывает озабоченность (как мы заменяем raii и деструкторы с Контекст-менеджеры ), но наличие имен переменных с нашего пути желательно.
Iife предлагает нам немного больше с точки зрения функциональности, так как они создают возможность для наших операций и позволяют нам получить ценность от этой области. Это полезно как для более простого управления потоком, так и для легко инициализации постоянных переменных.
Python не имеет ни одной из этих конструкций. Невозможно создать вложенную блокировку кода в Python (добавление другого уровня отступления могло бы просто жаловаться на неожиданные), и, хотя Lambdas существуют, они допускают только одно выражение, что делает их в основном неактуальными для IIFE. С другой стороны, Python предлагает нам две замечательные конструкции, которые можно использовать практически везде – классы и функции.
Классы и вложенные блоки 🧱🧱🧱
В Python как классы, так и функции могут быть вложены. Вы можете определить класс внутри класса, функцию в функции, класс в функции или функцию в классе. Все то же самое. Более того-вы можете иметь контроль потока как в функции (ну, очевидно,) и классовых тела (мета-спрограммирование много?). Кроме того, как вложенные функции, так и вложенные классы создают новые переменные прицелы, сохраняя свои внутренности внутри, а также являются закрытыми, способными захватить значения из их приоритетных областей. Таким образом, они являются идеальными инструментами для наших махинаций, изгибающихся на языке.
Во -первых, вложенные кодовые блоки. Я предлагаю вам следующее решение:
def f(x): print('Classes are great for creating blocks.') class _: y = x * 2 print(f'y = {y}') print('y is not defined here.') y f(21)
Определяя класс, мы создаем новую сферу. Внутри него мы можем делать все, что хотим, зная, что код будет выполнять встроенный и по порядку, и результаты не протекают в прицеле.
Тем не менее – есть некоторые предостережения. Во -первых, класс остается в масштабах, как и все переменные, определенные в нем. Они не могут быть собраны мусором, пока функция не завершится. Вы можете проверить это самостоятельно, пытаясь получить доступ к _.y.
В приведенном выше примере. Чтобы исправить это, нам нужно избавиться от класса или, по крайней мере, его содержимого. Есть много способов достичь этого:
# Replace the class with a bool @bool class _: x = 1 print(x) # Replace the class with None def empty(*args): return None @empty class _: x = 1 print(x) # Use a metaclass to delete all the variables inside the class class BlockMeta(type): def __new__(cls, name, bases, dict_): return super().__new__(cls, name, bases, {}) class Block(metaclass=BlockMeta): pass class _(Block): x = 1 print(x)
Я лично разорван между мета-классом, так как он явный и ясный, и @bool
Подход, как это требуется для дополнительного шаблона.
Вторая проблема с классами в качестве блоков заключается в том, что, хотя они могут быть свободно вложены, вложенный класс не может получить доступ к переменным своему классу гнезда, что делает блок-близости. У меня нет решения для этого в настоящее время.
Функции и iife 🐍🐍🐍
С решением для вложенных блоков в руке, пришло время получить надлежащий iife в Python. Для этого мы, естественно, будем использовать функцию. Наряду с ними, мы будем использовать лучшего друга функции – декоратор!
def iife(f): return f() def describe_number(n): @iife def message(): if n < 0: return f'{n} is smaller than 0' elif n > 0: return f'{n} is larger than 0' return f'{n} is 0' print(message) describe_number(-1) describe_number(0) describe_number(1)
Используя декоратор, мы сразу же называем функцию, привязывая имя функции к возвращаемому значению вместо самой функции. Функция, возвращающая Нет
(или без оператора возврата) просто свяжет имя с Нет
Анкет
Хотя это выглядит немного более грязно, это также может удвоиться в качестве решения для вложенных блоков. И в отличие от классового решения – оно может быть свободно вложено.
def iife(f): return f() def block(f): f() def f(x): print('Functions are great for creating blocks.') @block def _(): my_x = x + 1 @iife def y(): return my_x * 2 @block def _(): print(f'y = {y}') print('y is not defined here.') y f(20)
Вот и все на сегодня. Надеюсь, вам было повеселиться.
Змеиные глаза (серия 2 частей)
Оригинал: “https://dev.to/tmr232/snake-eyes-scopes-and-iife-50h2”