locallyscoped类的内省(python)

2024-09-30 20:21:26 发布

您现在位置:Python中文网/ 问答频道 /正文

当我试图通过Convert string to Python class object?中的一些建议使用内省从字符串导航到类时,我注意到给定的方法无法在函数的局部作用域中找到类。考虑下面的代码:

import sys

def f():
   class LocalClass:
       pass
   print LocalClass
   print 'LocalClass' in dir(sys.modules[__name__])

它给出了输出

__main__.LocalClass
False

我有点困惑,为什么根据类对象本身,LocalClass似乎属于主模块,但无法通过sys.modules访问。有人能解释一下吗

有没有办法从字符串生成类,即使该类仅在非全局范围内


Tags: to方法函数字符串modulesconvertstringobject
1条回答
网友
1楼 · 发布于 2024-09-30 20:21:26

在函数f中,LocalClass确实是局部的。您可以通过尝试__main__.LocalClass并看到AttributeError: 'module' object has no attribute 'LocalClass'被引发来看到这一点

至于类返回__main__.LocalClass的原因,是因为默认情况下,__repr__函数返回<cls.__module__>.<cls.__name__>

dir找不到它的原因是因为它只查看在其作用域中定义的变量LocalClass是本地的,因此如果您查看主模块,它将不会显示

从字符串创建类的方法有很多种

第一个也是最容易理解的方法是使用exec。现在你不应该只使用exec来处理随机的事情,这样我就不会使用这个方法了

第二种方法是使用type函数。它的帮助页面返回type(name, bases, dict)。这意味着您可以创建一个名为LocalClass的类,子类为object,属性foo设置为“bar”,方法是执行type("LocalClass", (object,), {"foo": "bar"})并在变量中捕获返回的类。您可以通过执行globals()["LocalClass"] = ...使类成为全局类

PS:获取主模块的一种更简单(不确定是否更漂亮)的方法是执行import __main__。这可以在任何模块中使用,但我通常建议不要使用它,除非您知道自己在做什么,因为一般来说,python人员不喜欢您做这种事情

编辑:查看链接问题后,您不希望动态创建新类,而是希望检索给定名称的变量。链接问题中的所有答案都可以做到这一点。我让你自己决定你最喜欢哪一个

EDIT2:LocalClass.__module____main__相同,因为这是您定义该类的模块。如果您在由__main__导入的模块Foo中定义了它(实际上并不是独立运行的),您会发现__module__将是“B”。尽管LocalClass是在__main__中定义的,但它不会自动进入全局表,因为它是一个类——在python中,正如您可能已经知道的那样,(几乎)一切都是一个对象。dir函数搜索范围中定义的所有变量。正如您在主范围中所看到的,它几乎等同于执行__dict__globals(),但有一些细微的区别。因为LocalClass是本地的,所以它没有在全局上下文中定义。但是,如果在函数f内执行locals(),您会发现LocalClass将出现在该列表中

相关问题 更多 >