python: оператор with в анонимных функциях - PullRequest
0 голосов
/ 26 декабря 2018

Можно ли использовать оператор with в анонимных функциях Python?Например, у меня есть функция, которая записывает 1 в файл:

def write_one(filename):
    with open(filename, 'wt') as fp:
        fp.write('1')

Но эта функция должна быть организована в dict:

my_functions = {
    ....
}

Очевидно, я могу написать этооператор для добавления этой функции к dict:

my_functions['write_one'] = write_one

Но проблема в том, что имя write_one все еще существует в текущей области.Как я могу ввести анонимную функцию, не загрязняя текущее пространство имен?

Для простых функций я могу использовать lambda.Для слегка сложных функций я могу вернуть кортеж для выполнения нескольких операторов (точнее, выражений).Но я не нашел способ умно использовать lambda, чтобы он мог работать с with операторами.Если это невозможно, то где это сказано в документации?

Решение с del write_one мне не нравится.Я не хочу, чтобы это имя вообще вводилось в текущем пространстве имен.

Одним словом, я хочу что-то вроде этого:

my_functions['write_one'] = def(filename):
    with open(filename, 'wt') as fp:
        fp.write('1')

Это немного неловко сПравила Python, основанные на отступах, я знаю.Но он делает свою работу.

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

В Python не так много пространств имен - функция в основном локальная.Это дает хороший намек на возможное решение:

def gen_functions():
    def f1(i):
        print(i)
    def f2(i):
        print(i+1)
    return f1,f2

my_funcs = dict(zip(('a','b'),gen_functions()))
my_funcs['a'](2)
my_funcs['b'](7)
f1(3)

Запустите это:

>py bla.py
2
8
Traceback (most recent call last):
  File "bla.py", line 11, in <module>
    f1(3)
NameError: name 'f1' is not defined

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

0 голосов
/ 26 декабря 2018

Лямбда-выражения весьма ограничены в том, что они могут делать.Из документов

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

Просто используйте полное определение функции.Если вы действительно хотите избежать загрязнения пространства имен, просто del имя впоследствии.

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

Если вы действительно хотите избежать этого, вы могли бы использовать конструктор function и динамически компилировать код и т. Д. Или использовать другой виддинамического выполнения кода, например, используя eval или exec.Но это почти наверняка не стоит проблем.Особенно, если вы можете просто del имя после того, как вы закончили использовать его.

Или, возможно, лучший подход - поместить все эти функции в другое пространство имен, например в другой модуль.

...