我不明白在没有括号的情况下调用类会发生什么。我的问题来自阅读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())
答案 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
根据需要创建新实例。