Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
373 views
in Technique[技术] by (71.8m points)

python - Built-in variable to get current function

I have a lot of functions like the following, which recursively call themselves to get one or many returns depending on the type of the argument:

def get_data_sensor(self, sensorname):
    if isinstance(sensorname, list):
        return [get_data_sensor(self, sensor) for sensor in sensorname]
    return get_data(os.path.join(self.get_info("path"), "{0}.npy".format(sensorname)))

I would like to call my function recursively without having to know my current function name, I don't want to have my function name twice in the code to limit copy-paste error.

Determine function name from within that function (without using traceback) shows how to get the actual function name, but I need the function itself to call it.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can abstract that logic outside the function entirely by using a decorator (see this thorough answer if you're unfamiliar with decorators):

from functools import wraps

def autolist(func):
    @wraps(func)
    def wrapper(args):
        if isinstance(args, list):
            return [func(arg) for arg in args]
        return func(args)
    return wrapper

This decorator can be applied to any function requiring the pattern, which now only needs to implement the scalar case:

>>> @autolist
... def square(x):
...     return x ** 2
...
>>> square(1)
1
>>> square([1, 2, 3])
[1, 4, 9]

If you're applying it to a method, as self implies, you'll also need to take that argument into account in the wrapper. For example, if the relevant argument is always the last one you could do:

def autolist(func):
    @wraps(func)
    def wrapper(*args):
        *args, last_arg = args
        if isinstance(last_arg, list):
            return [func(*args, arg) for arg in last_arg]
        return func(*args, last_arg)
    return wrapper

This would work on methods, too:

>>> class Squarer:
...     @autolist
...     def square(self, x):
...             return x ** 2
...
>>> Squarer().square(1)
1
>>> Squarer().square([1, 2, 3])
[1, 4, 9]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...