Python类如何以不同名称初始化?WMI库源码实现困惑
找到合适的WMI库
昨天我在Python项目里需要用到WMI,找了一圈发现了对应的Python库,这个库的文档做得相当完善,还有一大堆实用的示例,比如获取本地进程信息:
import wmi c = wmi.WMI () for process in c.Win32_Process (): print process.ProcessId, process.Name
或者连接远程机器:
import wmi c = wmi.WMI ("some_other_machine")
查看源码时的疑惑
我好奇WMI类初始化时能传入哪些参数,于是去翻了源码。原本以为会直接看到类似class WMI:或者def WMI()的定义,结果实际看到的是一个名为_wmi_namespace的类:
# # class WMI # class _wmi_namespace: """A WMI root of a computer system. The classes attribute holds a list of the classes on offer. This means you can explore a bit with things like this:: c = wmi.WMI () for i in c.classes: if "user" in i.lower (): print i """ def __init__ (self, namespace, find_classes): _set (self, "_namespace", namespace) # # wmi attribute preserved for backwards compatibility # _set (self, "wmi", namespace) self._classes = None self._classes_map = {} # # Pick up the list of classes under this namespace # so that they can be queried, and used as though # properties of the namespace by means of the __getattr__ # hook below. # If the namespace does not support SubclassesOf, carry on # regardless # if find_classes: _ = self.classes
虽然注释里有相关说明,但我还是搞不懂它的实现逻辑,尤其是Python类怎么能以不同的名称完成初始化?
核心问题解答:类的别名与工厂函数实现
其实这是Python里很常见的技巧,主要通过两种方式实现:
1. 类的别名赋值
模块里可能直接把内部类_wmi_namespace赋值给了对外暴露的WMI名称,比如:
# 在wmi模块的某个地方 WMI = _wmi_namespace
这样你调用wmi.WMI()的时候,本质上就是在实例化_wmi_namespace类,只是名字被替换成了更简洁友好的WMI。这种方式常用于隐藏内部实现细节,用下划线开头的类名表示这是内部私有类,对外只暴露用户需要的名字。
2. 工厂函数包装
另一种可能是模块里定义了一个名为WMI的工厂函数,它内部负责创建_wmi_namespace的实例,还能做一些额外的逻辑处理,比如默认参数设置、异常捕获等:
def WMI(namespace="root/cimv2", find_classes=True, computer_name=None, user=None, password=None): # 这里可以做一些参数预处理、权限验证等逻辑 namespace_obj = _wmi_namespace(namespace, find_classes) # 如果需要连接远程机器,可能在这里添加额外配置 if computer_name: # 处理远程连接逻辑 pass return namespace_obj
这种方式比直接暴露类更灵活,能给用户提供更简洁的调用接口,同时把复杂的初始化逻辑封装在工厂函数里。
至于你看到的_wmi_namespace类的__init__方法,它接收namespace和find_classes两个参数,这说明当你调用wmi.WMI()时,传入的参数最终会传递给这个内部类的初始化方法,只是中间可能经过了工厂函数的处理(比如设置默认值)。
内容的提问来源于stack exchange,提问作者zviad

