- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
从表面上看,C-API 函数 PyModule_New
和 PyModule_NewObject
显然创建了一个新的模块对象。
official Python Documentation为 PyModule_NewObject
提供以下解释:
Return a new module object with the name attribute set to name. Only the module’s doc and name attributes are filled in; the caller is responsible for providing a file attribute.
PyModule_New
做同样的事情,除了它接受 C 字符串 (char*
) 作为模块名称的参数,而不是 PyObject*
字符串。
好吧,这很简单,但是......
我的问题是:调用API函数PyModule_NewObject
有什么用?
当然,从理论上讲,这对于您想要动态创建新模块的情况来说会很棒。但问题是,在实践中,在创建一个新的模块对象之后,对它做任何有用的事情的唯一方法是将对象(如方法、类、变量等)添加到模块的 __dict__
属性。这样模块的用户可以导入它并实际使用它做一些事情。
问题是模块的 __dict__
属性是只读:
>>> import re
>>> x = re
>>> re.__dict__ = { "foo" : "bar" }
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: readonly attribute
因此,据我所知,在实践中,实际上没有办法对动态创建的模块做任何有用的事情。那么,C API 函数 PyModule_New
的目的是什么?
最佳答案
PyModule_New
是模块对象的构造函数。它也暴露给纯 Python 代码,作为 types.ModuleType
类的 __new__
方法。
用户代码可能很少需要使用其中任何一个,因为您通常通过导入模块来获取模块。但是,Python 解释器使用的机制使用 PyModule_New
在请求导入时生成模块对象。
您可以在 import.c
in the Python source 中看到这个:
/* Get the module object corresponding to a module name.
First check the modules dictionary if there's one there,
if not, create a new one and insert it in the modules dictionary.
Because the former action is most common, THIS DOES NOT RETURN A
'NEW' REFERENCE! */
PyImport_AddModule(const char *name)
{
PyObject *modules = PyImport_GetModuleDict();
PyObject *m;
if ((m = PyDict_GetItemString(modules, name)) != NULL &&
PyModule_Check(m))
return m;
m = PyModule_New(name);
if (m == NULL)
return NULL;
if (PyDict_SetItemString(modules, name, m) != 0) {
Py_DECREF(m);
return NULL;
}
Py_DECREF(m); /* Yes, it still exists, in modules! */
return m;
}
至于如何在新模块对象中设置值,您可以使用常规属性访问。在 Python 代码(而不是 C)中,这很简单:
import types
mymodule = types.ModuleType("mymodule")
mymodule.foo = "foo"
请注意,除非您做一些额外的工作,否则无法将以这种方式创建的模块导入到其他任何地方。例如,您可以将它添加到模块查找字典 sys.modules
:
import sys
sys.modules["mymodule"] = mymodule
现在其他模块可以按名称导入mymodule
。
关于python - PyModule_New 的目的和用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15726256/
从表面上看,C-API 函数 PyModule_New 和 PyModule_NewObject 显然创建了一个新的模块对象。 official Python Documentation为 PyMod
我是一名优秀的程序员,十分优秀!