Как вернуть значение с помощью динамических вызовов методов через getattr()

У меня есть класс, который называется, который запускает командную строку цикла while, я использую dir() а также getattr() динамически создавать список методов для командной оболочки. Я хочу вернуть значения, но возвращение из динамически вызываемого метода просто завершает основной цикл 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()

1 ответ

Решение

getattr и вернуть значения

Когда вы делаете 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()

переменные value а также towels являются 42 а также "Remember your towel" в обоих случаях.

Это должно ответить на ваши вопросы.

ТЕМ НЕ МЕНИЕ:

Основная проблема в коде

Однако основная проблема в коде не имеет ничего общего с getattr,

в help метод, который вы ссылаетесь на f функция, которую вы никогда не определяете, так что возникает исключение.

Но большая проблема в конце __main__:

except:
    pass

в конце. Вы никогда не должны делать это: вы заставляете ошибки замолчать, что затрудняет их отладку.

Если вы хотите сделать свой код устойчивым к ошибкам, вы должны перехватить все ошибки и сообщить о них где-нибудь, например, используя сообщения журнала:

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 функция.

  • все команды возвращаются None или строка. Когда вы исправите код, как указано выше, вы получите много ошибок из строки 63: f()

PS: Если вы начинаете с python, посмотрите на PEP8, официальные рекомендации по стилю Python

Другие вопросы по тегам