简体   繁体   中英

Call a Function by alias in a Decorator

The current code I have, allows the function to call the wrapper decorator, and uses the function name in its code. However, I'm looking for a way to give the function a 'alias' in a way as an argument. Here's the current code:

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]()

For example I would want to be able to call the function by a name such as '!foo' from the user input, so maybe the argument would look like @command(name='!foo') , I just don't know where to go from there to use that argument in the decorator since it already has an argument.

I attempted

# Command wrapper
ALLCOMMANDS = {}
def command(name):
    ALLCOMMANDS[name] = name
    return name

but keep getting errors and I assume I am missing something

You should read up a bit more on python decorators. You're getting an error with:

def command(name):
    ALLCOMMANDS[name] = name
    return name

Because of the return name .

Decorators are just syntactic sugar. This:

@command
def foo():
    print('bar')

Is equivalent to:

def foo():
    print('bar')

foo = command(foo)

From this you can see why your original decorator works. At the end you return function .

Things get a little tricker when you have a decorator that takes arguments. Desugared the following:

@command('nickname')
def foo():
    print('bar')

Looks like this:

def foo():
    print('bar')

foo = command('nickname')(foo)

So, to write a decorator that takes arguments, the decorator needs to return a function that takes the function to decorate as an argument:

def command(nickname):
    def wrapped(f):
        ALLCOMMANDS[nickname] = f
        return f
    return wrapped

Also consider making ALLCOMMANDS an attribute on your command instead of a global ( UPPER_SNAKE is usually reserved for constants):

def command(nickname):
    def wrapped(f):
        command._functions[nickname] = f
        return f
    return wrapped

command._functions = {}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM