对本地范围的类(python)的反思

时间:2015-07-29 08:04:43

标签: python python-2.7

在尝试使用内省通过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访问。有人可以解释一下吗?

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

1 个答案:

答案 0 :(得分:2)

在函数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,属性type("LocalClass", (object,), {"foo": "bar"})设置为&#34; bar&#34;通过执行globals()["LocalClass"] = ...并在变量中捕获返回的类。您可以通过执行import __main__

使全局变为全局

PS:通过LocalClass.__module__更简单(不确定,更漂亮)获取主模块的方法。这可以在任何模块中使用,但我通常建议不要使用它,除非你知道你在做什么,因为一般来说,python人不喜欢你做这种事情。

编辑:在查看链接的问题之后,您不想动态创建新类,而是根据它的名称检索变量。链接问题中的所有答案都会这样做。我会让你决定你最喜欢哪一个

EDIT2:__main__Foo相同,因为那是您定义类的模块。如果您在__main__导入的模块__module__中定义了它(并且实际上并非单独运行),您会发现LocalClass将是&#34; B&#34;。即使在__main__中定义dir,它也不会因为它是一个类而自动进入全局表 - 在python中,你可能已经知道了,(几乎)一切都是一个东西。 __dict__函数搜索范围中定义的所有变量。当您在主要范围内查看时,它几乎等同于执行globals()LocalClass但略有不同。因为locals()是本地的,所以它不是在全局上下文中定义的。如果您在功能f内进行了LocalClass,则会发现$this->db->select("initiation.*, project.projectname,subproject.subprojectname, concat(employee.firstname,' ',employee.lastname) as 'name'") ->from('initiation') ->join('project','initiation.projectid=project.id') ->join('employee','initiation.leaderid = employee.id') ->join('subproject','initiation.subprojectid=subproject.id','left'); $query = $this->db->get(); $result = $query->result_array();//changed return $result;//changed 会出现在该列表中