#python #function #decorator
#python #функция #декоратор
Вопрос:
Текущий код, который у меня есть, позволяет функции вызывать декоратор оболочки и использует имя функции в своем коде. Тем не менее, я ищу способ присвоить функции «псевдоним» в некотором роде в качестве аргумента. Вот текущий код:
import os, sys
# Take user input
message = input('type command: ')
# Command wrapper
ALLCOMMANDS = {}
def command(function):
ALLCOMMANDS[function.__name__] = function
return function
# Commands
@command
def foo():
print("bar")
@command
def goo():
print('ber')
# Run appropriate command
if message in ALLCOMMANDS:
ALLCOMMANDS[message]()
Например, я хотел бы иметь возможность вызывать функцию по имени, такому как ‘!foo’, из пользовательского ввода, поэтому, возможно, аргумент будет выглядеть как @command(name='!foo')
, я просто не знаю, куда идти дальше, чтобы использовать этот аргумент в декораторе, поскольку у него уже есть аргумент.
Я попытался
# Command wrapper
ALLCOMMANDS = {}
def command(name):
ALLCOMMANDS[name] = name
return name
но продолжаю получать ошибки, и я предполагаю, что мне чего-то не хватает
Комментарии:
1. Если вы будете следовать этому, вы сможете передать аргумент name: python-3-patterns-idioms-test.readthedocs.io/en/latest /…
Ответ №1:
Вам следует почитать немного больше о декораторах python. Вы получаете ошибку с:
def command(name):
ALLCOMMANDS[name] = name
return name
Из-за return name
.
Декораторы — это просто синтаксический сахар. Это:
@command
def foo():
print('bar')
Эквивалентно:
def foo():
print('bar')
foo = command(foo)
Из этого вы можете понять, почему работает ваш оригинальный декоратор. В конце вы return function
.
Все становится немного сложнее, когда у вас есть декоратор, который принимает аргументы. Было предложено следующее:
@command('nickname')
def foo():
print('bar')
Выглядит так:
def foo():
print('bar')
foo = command('nickname')(foo)
Итак, чтобы написать декоратор, который принимает аргументы, декоратору необходимо вернуть функцию, которая принимает функцию для оформления в качестве аргумента:
def command(nickname):
def wrapped(f):
ALLCOMMANDS[nickname] = f
return f
return wrapped
Также рассмотрите возможность создания ALLCOMMANDS
атрибута в вашей команде вместо глобального ( UPPER_SNAKE
обычно зарезервирован для констант):
def command(nickname):
def wrapped(f):
command._functions[nickname] = f
return f
return wrapped
command._functions = {}
Комментарии:
1. Ах, имеет смысл. Ценю подробную справку, и я выполню эти рекомендации