在装饰器中通过别名调用函数

时间:2019-03-15 18:43:38

标签: python function decorator

我拥有的当前代码允许该函数调用包装装饰器,并在其代码中使用函数名称。但是,我正在寻找一种以某种方式为函数赋予“别名”的方法。这是当前代码:

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 个答案:

答案 0 :(得分:2)

您应该阅读有关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 = {}