如何基于名称在全局范围内创建函数,用同一名称调用方法

2024-09-30 02:19:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在函数范围内基于^{}实例的相应方法生成一组函数。我感兴趣的函数/方法有:

['debug', 'info', 'warning', 'error', 'critical', 'exception']

它们都有相同的原型

现在我可以明确地说:

global debug, info, warning, error critical, exception

然后继续def每一个。我检查过了,效果很好。问题是我得重复一遍

所以我有一个名为myloglogging.Logger的实例,它已经是一个全局的。下面是我想要的,但是通过分别硬编码函数/方法的名称:

global debug
def debug(msg, *args, **kwargs):
    if mylog: mylog.debug(msg, *args, **kwargs)

为了简洁起见,我将在编写示例时只考虑debug,跳过其余部分。不幸的是,真正的代码有些复杂,因此使用lambda的要求似乎没有得到满足(单语句,对吧?)

所以我明显的想法是在mylog上使用getattr"debug"的名字,然后简单地调用我在定义的函数中得到的任何东西,并通过名字将其添加到globals()dict。示例:

for fct in ['debug']:
    def x(msg, *args, **kwargs):
        if mylog: getattr(mylog, fct)(msg, *args, **kwargs)
    globals()[fct] = x

但我认为这实际上是不合法的,因为我调用的应该是类方法,就好像它是静态方法一样。尽管如此,这个“工作”,但每个输出行后面都跟有另一行,即:None

所以我想我可以把这个实例作为第一个参数来传递。毕竟这就是self的意义所在:

for fct in ['debug']:
    def x(msg, *args, **kwargs):
        if mylog: getattr(mylog, fct)(mylog, msg, *args, **kwargs)
    globals()[fct] = x

这给了我:

TypeError: not all arguments converted during string formatting

我从中得到的效果是一样的:

for fct in ['debug']:
    import types
    def x(msg, *args, **kwargs):
        if mylog: types.MethodType(getattr(mylog, fct), mylog)(msg, *args, **kwargs)
    globals()[fct] = x

我基于这个问题的公认答案:Dynamically bind method to class instance in python

应用Alex Martelli的答案here会产生相同的错误

我做错什么了?我怎样才能达到想要的行为而不必重复我自己


完全回溯:

Traceback (most recent call last):
  File "/usr/lib64/python2.6/logging/__init__.py", line 776, in emit
    msg = self.format(record)
  File "/usr/lib64/python2.6/logging/__init__.py", line 654, in format
    return fmt.format(record)
  File "/usr/lib64/python2.6/logging/__init__.py", line 436, in format
    record.message = record.getMessage()
  File "/usr/lib64/python2.6/logging/__init__.py", line 306, in getMessage
    msg = msg % self.args
TypeError: not all arguments converted during string formatting

完整的脚本,基于上面的第一个示例代码:

#!/usr/bin/env python
import sys, logging

def setup_logging():
    global mylog
    mylog = logging.getLogger('foobar')
    mylog.addHandler(logging.StreamHandler())
    for fct in ['debug']:
        def x(msg, *args, **kwargs):
            if mylog: getattr(mylog, fct)(mylog, msg, *args, **kwargs)
        globals()[fct] = x

def main():
    setup_logging()
    debug('TEST LOG MESSAGE')

if __name__ == '__main__':
    sys.exit(main())

Tags: 方法函数indebugifusrloggingdef
1条回答
网友
1楼 · 发布于 2024-09-30 02:19:41

在我看来,这应该行得通:

debug = mylog.debug

或:

debug, info, warning, error, critical, exception = (
    mylog.debug, mylog.info, mylog.warning, 
    mylog.error, mylog.critical, mylog.exception)

动态设置:

for fct in ('debug', 'info', 'warning'):
    globals()[fct] = getattr(mylog, fct)

for循环for fct in ('debug'):在字符串'debug'上迭代,您需要一个逗号for fct in ('debug',):使其成为元组

另请注意,一个构造,例如:

for fct in ['debug']:
    def x(msg, *args, **kwargs):
        if mylog: getattr(mylog, fct)(msg, *args, **kwargs)
    globals()[fct] = x

定义调用函数时使用当前值“fct”。您需要额外的间接寻址级别来处理多个日志记录方法。e、 g

def make_log(fct):
    def x(msg, *args, **kwargs):
        if mylog: getattr(mylog, fct)(msg, *args, **kwargs)
    return x

for fct in ['debug','info']:
    globals()[fct] = make_log(fct)

相关问题 更多 >

    热门问题