如何通过 getattr() 使用动态方法调用 return 值

How to return value with dynamic method calls through getattr()

我有一个调用的 class 运行 while 循环命令提示符,我正在使用 dir()getattr() 动态创建命令的方法列表 shell。我想要 return 值,但是动态调用方法中的 return 只是退出到主 while 循环,为什么我该如何解决这个问题?

class myClass :
    def __init__(self) :
        self.commands = []
        for x in dir(self) :
                k = getattr( self, x )
                if hasattr(k, '__func__') :
                    self.commands.append(x)
            # strips off __init__ and __main__
            self.commands = self.commands[2:]

    def help(self, args=None) :
        for x in self.commands :

            ####
            #### The issue is here
            print('Command: {}'.format(x))
            f = getattr(self, x)('-h')
            desc = f()
            print('Description: {}'.format(desc))
        ...
        return SomeValue

    def cmd_b(self, args=None) :
        if args == '-h' :
            return 'Some description'
        ...
        return SomeValue

    def cmd_c(self, args=None) :
        ...
        return SomeValue

    def __main__(self) :
        while True :
            command = input(self.ENV['PS1'])
            command += ' '
            command = command.split()
            print(command)
            if len(command) > 1 :
                print(command)
                print(len(command))
                args = command[1:]
                command = command[0]
            else :
                command = command[0]
                args = None

            if command == 'exit'  :
                break

            if command not in dir(self) :
                print("Command `{}` not found".format(command))
                continue
            print(command)
            f = getattr( self, command )(args)
            x = f()

getattr 和 return 值

当您执行getattr(self, attr)时,您会返回相应的对象,这与直接调用属性相同。例如:

class A:
    def __init__(self):
        self.v = 42
    def func(self):
        return "Remember your towel"

a = A()

以下是等价的

value = a.v
towel = a.func()

value = getattr(a, 'v')
towel = getattr(a, 'func')()

f = getattr(a, 'func')
towel = f()

变量valuetowels在这两种情况下都是42"Remember your towel"

这应该可以回答您的问题。

但是:

代码中的主要问题

然而代码中的主要问题与getattr无关。

help 方法中,您引用了一个您从未定义的 f 函数,因此会引发异常。

但是最大的问题是在__main__的结尾:

except:
    pass

最后。你应该永远不要这样做:你正在消除错误,使得调试变得非常困难。

如果你想让你的代码对错误有弹性,你应该捕获所有错误并在某个地方报告它们,例如使用 log messages:

import logging

log = logging.getLogger()
# set up the logger

while:
    try:
        func()
    except Exception:
        log.exception('my nice message for the user')

如果你在你的代码中做这样的事情,那么捕获像未定义的 f 函数这样的错误会容易得多。

一些建议:

  • help 函数中,您遍历所有命令,包括 help 本身,并打印它们的帮助。您实现帮助的方式会导致无限递归。您应该跳过从 help 函数调用 help

  • 所有命令return None或一个字符串。当您按照上面的指示修复代码时,您会从第 63 行得到很多错误:f()

ps:如果你是从python开始的,看看PEP8, the official python style guidelines