我有一堂这样的课:
class Metrics:
meters = {}
for subscription in SUBSCRIPTION_TYPES:
meters[subscription] = metrics.new_meter(subscription)
@staticmethod
def get_meter_data(field, key):
return Metrics.meters[field].get()[key]
@staticmethod
def track(subscription, value):
Metrics.meters[subscription].notify(value)
gauge_for_passport.set_function(lambda: Metrics.meters[subscription].get()["count"])
基本上,我只希望计量字典初始化一次,因为它将跟踪我的应用程序中的某些事件,因此我在类主体中有 for
循环。这是正确的方法吗?
我是否还应该使用 classmethod
以便可以使用 cls
并将类本身传递给方法,而不是直接调用 Metrics
?
最佳答案
类在模块运行时“初始化”。所以当你写这个时:
# my_module.py
class Metrics:
meters = {}
for subscription in SUBSCRIPTION_TYPES:
meters[subscription] = metrics.new_meter(subscription)
...for 循环在导入 my_module 时执行。
在我看来,您真正想要的是一个模块,而不是一个类。任何给定模块只有一个实例。
# metrics.py module
meters = {}
for subscription in SUBSCRIPTION_TYPES:
meters[subscription] = new_meter(subscription)
def get_meter_data(field, key):
return meters[field].get()[key]
def track(subscription, value):
meters[subscription].notify(value)
gauge_for_passport.set_function(lambda: meters[subscription].get()["count"])
当你想要它“实例化”时,你只需导入它:
# other_module.py
import metrics
如果您确实不想将此模块放在单独的文件中,可以通过多种方法在另一个模块中动态创建模块。但老实说,这可能不值得这么麻烦,而且我什至不确定如何编写该模块并延迟其执行。
延迟类创建的另一个选项可能是编写一个类工厂,这是一种 Python 方法,根据您的用例可能会有意义:
def get_metrics():
class Metrics:
meters = {}
for subscription in SUBSCRIPTION_TYPES:
meters[subscription] = metrics.new_meter(subscription)
@staticmethod
def get_meter_data(field, key):
return Metrics.meters[field].get()[key]
@staticmethod
def track(subscription, value):
Metrics.meters[subscription].notify(value)
gauge_for_passport.set_function(lambda: Metrics.meters[subscription].get()["count"])
return Metrics
通过这种方式,您可以控制类何时运行。但你的示例代码对我来说确实看起来不太像一个类;它看起来像是属于同一个命名空间的一堆工具。
让我们来点可笑的
回到动态模块创建的想法:您可以将这两个想法结合在一起并执行如下操作:
from types import ModuleType
def init_metrics_module():
"""This is a function to delay creation of the module below."""
meters = {}
for subscription in SUBSCRIPTION_TYPES:
meters[subscription] = new_meter(subscription)
def get_meter_data(field, key):
return meters[field].get()[key]
def track(subscription, value):
meters[subscription].notify(value)
gauge_for_passport.set_function(lambda: meters[subscription].get()["count"])
# create module
module_dict = locals().copy()
metrics = ModuleType("metrics")
metrics.__dict__.update(module_dict)
return metrics
然后当你需要它时:
metrics = init_metrics_module()
type(metrics) # <class 'module'>
关于python-3.x - 如何在Python中初始化类而不是实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57398066/