调用不带括号的python类有什么作用?

时间:2018-06-20 14:57:59

标签: python

我不明白在没有括号的情况下调用类会发生什么。我的问题来自阅读Python HOWTO: Logging Cookbook。具体来说,我试图了解我在此问题结尾处添加的食谱。该食谱的目的是指示logging格式化程序从日志记录配置字典中使用UTC时间。

定义了一个类

class UTCFormatter(logging.Formatter):
    converter = time.gmtime

,然后仅按名称使用;没有括号。

'formatters': {
            'utc': {
                '()': UTCFormatter,   # <-------------------Class used here
                'format': '%(asctime)s %(message)s',
            },

这里发生了什么,为什么以这种方式调用类比创建类的实例有好处? 也就是说,我可以搜索哪些关键字(“类”之外)来帮助我在python文档中找到有关此信息的更多信息?

完整食谱:

import logging
import logging.config
import time

class UTCFormatter(logging.Formatter):
    converter = time.gmtime

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'utc': {
            '()': UTCFormatter,
            'format': '%(asctime)s %(message)s',
        },
        'local': {
            'format': '%(asctime)s %(message)s',
        }
    },
    'handlers': {
        'console1': {
            'class': 'logging.StreamHandler',
            'formatter': 'utc',
        },
        'console2': {
            'class': 'logging.StreamHandler',
            'formatter': 'local',
        },
    },
    'root': {
        'handlers': ['console1', 'console2'],
   }
}

if __name__ == '__main__':
    logging.config.dictConfig(LOGGING)
    logging.warning('The local time is %s', time.asctime())

1 个答案:

答案 0 :(得分:3)

仅使用类的名称(在您的情况下为UTCFormatter)不会实例化该类。相反,UTCFormatter是一个变量,它指向类型为type的值:

In [1]: class Foo:
   ...:     pass
   ...: 

In [2]: type(Foo)
Out[2]: type

该变量可用于通过UTCFormatter()创建新实例,但也可以像其他任何变量一样使用。特别是,它可以传递给函数并绑定到其他名称。例如,您可以执行以下操作:

In [3]: def my_function(some_class):
   ...:     print('Creating an instance of {}'.format(some_class.__name__))
   ...:     return some_class()
   ...: 

In [4]: foo = my_function(Foo)
Creating an instance of Foo

In [5]: foo
Out[5]: <__main__.Foo at 0x7f017451e438>

这在许多情况下很有用。在您的配方中,通过指定一个类(UTCFormatter)和一个名称('utc')一次定义一个格式化程序。然后,当您配置其他处理程序以使用该格式程序时,该定义就会重新使用。例如

'console1': {
    'class': 'logging.StreamHandler',
    'formatter': 'utc',
},

要从您的配置中构建实际的记录器层次结构,logging.config.dictConfig不需要一个UTCFormatter的实例(如果您通过UTCFormatter()就会得到),但每个实例一个您配置为使用该格式化程序的处理程序(您的情况下为两个)。通过传递类本身而不是实例,可以使dictConfig根据需要创建新实例。