【问题标题】:Iterate through functions in another module遍历另一个模块中的函数
【发布时间】:2020-10-16 09:56:15
【问题描述】:

如何从当前执行位置迭代特定模块中的所有函数?

以下是我迄今为止所做的一些细节:

我创建了一个名为“test_cases”的包,其中包含一个模块“test_cases”,其中包含许多功能。我想创建某种循环来执行 test_case 模块中的每个函数。

main() 的第一行下面是test_cases.test_cases.tc_1(),这只是为了测试我的脚本是否可以调用特定函数并且它可以工作。困扰我的是“循环”方面。

这是我的代码的大致思路:

def main():
    # test_cases.test_cases.tc_1()
    for _, test in test_cases.test_cases:
        test

我读过this post,但答案建议使用for name, val in my_module.__dict__.iteritems():,但是根据PEP 469iteritems() 不是python 3.8 中__dict__ 的属性(假设我没看错)。我也读过this post,但还不清楚。所以我有点困惑该怎么做。

我正在运行 Windows 10、PyCharm2020.1.2、Python 3.8

编辑 1

这是我的新 main() 函数,items() 用作迭代器。调试时,它似乎会逐步遍历我的test_case 模块的__name__, __doc__, __package__ 等元素(这些元素叫什么?)。然后它会识别我的函数tc_1 并尝试执行它但没有任何反应。我希望它能够运行print() 语句。我在下面附上了我的功能以供参考。这是怎么回事?

def main():
    for name, test in test_cases.test_cases.__dict__.items():
        if callable(test):
            test

# tc_1 is in the test_cases module 
def tc_1():
    print("TEST CASE ONE EXECUTED")

编辑 2

最后一个问题不包括test 后面的括号。纠正此问题后,循环将按预期工作。以下是参考代码:

def main():
    for name, test in test_cases.test_cases.__dict__.items():
        if callable(test):
            test()

【问题讨论】:

    标签: python python-3.x loops module iteration


    【解决方案1】:

    您是否尝试过使用getattr() function?您可以将它与@Reedinator 提到的过滤后的模块列表结合起来

    这是一个如何使用它的示例:

    # mymodule.py
    def func_A():
        return "Hello this is function A!"
    
    
    def func_B():
        return "Function B is counting bottles on the wall ..."
    
    
    def func_C():
        return "Function C ... well let's see ..."
    
    # in python shell
    >>> import mymodule
    >>> lst = [x for x in dir(mymodule) if not x.startswith('__')]
    >>> print(lst)
    ['func_A', 'func_B', 'func_C']
    
    >>> for f in lst:
    ...     el = getattr(mymodule, f)
    ...     el()
    ... 
    'Hello this is function A!'
    'Function B is counting bottles on the wall ...'
    "Function C ... well let's see ..."
    

    【讨论】:

    • 这篇文章也可能有帮助:tomassetti.me/…
    • 嗨@Fadi,我还没有尝试过 getatt() 函数。我想我已经解决了这个问题,请参阅上面的编辑。您对当前的解决方案有何看法?
    • 我会犹豫是否使用__dict__ ...请参阅this comment。我喜欢callable(object)的测试。我假设可调用函数是那些没有下划线的函数。
    • 你是对的。 __dict__ 引起了问题。使用__dict__ 识别所有功能的问题在于,它会提取归属于该模块的所有内容,其中包括任何imports。所以我采用了你的if x.startswith('tc') 方法,所以在使用__dict__ 之后,我只执行以tc 开头的函数。感谢您的意见!
    【解决方案2】:

    在 python 3 字典中有一个 .items() 方法。我相信.iteritems() 是特定于 Python 2 的。 python 3中可用方法的简单测试:

    >>>test = {}
    >>>dir(test)
    ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
    

    编辑

    您需要使用要丢弃的名称变量进行排序。如果你所有的测试都以“test”开头,那么就运行

    for name, test in test_cases.test_cases.__dict__.items():
        if name.startswith("test") and callable(test):
            test()
    

    这真的归结为只有你会具体知道如何过滤掉函数,但你总是可以添加更多的逻辑条件。只需使用函数的实际名称即可。

    【讨论】:

    • 您是否建议我以某种方式使用dir() 来遍历我的 test_case 模块中的函数? @Reedinationer
    • @Tim51 不。我建议您使用for name, val in my_module.__dict__.items() 而不是for name, val in my_module.__dict__.iteritems()dir() 是为了告诉你 .iteritems() 不是 python 3 字典的可用方法/属性,而 .items()
    • 知道了。我已经做到了,它似乎“执行”​​了可调用函数。但是该功能并没有达到我的预期。我已经更新了我的帖子,并进行了解释。 @Reedinationer
    • @Tim51 看来您的缩进已关闭,但也许您只是错误地发布了它。你有test 的地方也缺少括号,所以它实际上并没有做任何事情。你需要test()。您应该可以使用 print(test) 和 print(test()). Without parenthesis you will get ` (或类似的东西)来验证这一点,而使用括号,您将看到打印出函数的返回值(@ 987654335@ 除非你指定)
    • 缩进是错字。它已得到纠正。缺少的“ () ”是问题所在。感谢您的时间和支持! @Reedinationer
    猜你喜欢
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 2021-11-10
    • 2016-08-09
    • 1970-01-01
    • 2016-05-31
    • 2019-05-02
    • 1970-01-01
    相关资源
    最近更新 更多