Могу ли я определить magic_arguments для моего i python magi c без использования метода декоратора? - PullRequest
0 голосов
/ 28 февраля 2020

Я определил пользовательский я Python волхвов c так:

%%writefile pymagic.py

from IPython.core import magic_arguments

@magic_arguments.magic_arguments()
@magic_arguments.argument('--include', '-i', nargs='+', help='Pass file patterns to include')
@magic_arguments.argument('--omit', '-o', nargs='+', help='Pass file patterns to omit')
def pymagic(line, cell):
    args = magic_arguments.parse_argstring(pymagic, line)
    ip = get_ipython()
    out = ip.run_cell(cell)
    return args, 'test'

def load_ipython_extension(ipython):
    ipython.register_magic_function(pymagic, magic_kind='cell')

Я могу использовать его так:

%load_ext pymagic

%%pymagic --include /home/test/a* --omit /home/test/b*
a = [1,2,3]
# Output: (Namespace(include=['/home/test/a*'], omit=['/home/test/b*']), 'test')

Теперь я могу это сделать без использования декораторов @magic_arguments?

Причина, по которой я этого хочу, заключается в том, что я должен избегать глобального импорта модуля I Python, поскольку он вызывает некоторые другие неожиданные проблемы. Это означает, что я должен переместить импорт 'from I Python .core import magic_arguments' из глобальной области видимости, предпочтительно внутри функции load_python_extension ().

Я думаю о достижении чего-то подобного, что позволило бы мне избавиться от глобального импорта I python .core: (Приведенный ниже фрагмент является лишь приблизительным описанием и не синтаксически правильным )

def pymagic(line, cell):
    args = magic_arguments.parse_argstring(pymagic, line)
    ip = get_ipython()
    out = ip.run_cell(cell)
    return args, 'test'

def load_ipython_extension(ipython):
    from IPython.core import magic_arguments
    magic_arguments.add_magic_arg(func=pymagic, arg_attrs=('--include', '-i', nargs='+', help='Pass file patterns to include'))
    magic_arguments.add_magic_arg(func=pymagic, arg_attrs=('--omit', '-o', nargs='+', help='Pass file patterns to omit'))
    ipython.register_magic_function(pymagic, magic_kind='cell')

Возможно ли это?

1 Ответ

0 голосов
/ 28 февраля 2020

Конечно, вы можете делать то, что вы просите. Применение декораторов, например:

@foo
@bar
def baz():
    pass

(почти) эквивалентно выполнению этого вручную следующим образом:

def baz()
    pass

baz = foo(bar(baz))

Единственное отличие состоит в том, что при синтаксисе @ недекорированная функция никогда не присваивается пространству имен.

Обратите внимание, что декораторы применяются снизу вверх (bar вызывается первым, а его результаты передаются в foo)!

В вашей спецификации c case, вы можете сделать:

def load_ipython_extension(ipython):
    from IPython.core import magic_arguments
    global pymagic
    pymagic = magic_arguments.add_magic_arg(func=pymagic, arg_attrs=('--omit', '-o', nargs='+', help='Pass file patterns to omit'))
    pymagic = magic_arguments.add_magic_arg(func=pymagic, arg_attrs=('--include', '-i', nargs='+', help='Pass file patterns to include'))
    pymagic = magic_arguments(pymagic)
    ipython.register_magic_function(pymagic, magic_kind='cell')

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

...