Python类实例内省

时间:2016-04-24 21:58:27

标签: python oop instance introspection

从内省角度来看,有一种方法可以在不创建实例的情况下获取类实例变量。创建实例时很容易:

class Super:
    def __init__(self, name):
        self.name = name

class Sub(Super):
    pass

a = Super("Nice_Name")

print(a.__dict__.keys())

但我希望在不创建实例的情况下获取该信息,只是为了内省。有办法吗?

2 个答案:

答案 0 :(得分:0)

不,你不能,因为python不是statically typed language,所以在实例化对象之前,该对象没有类型。例如,想象一下这样的类:

class A:
def __init__(self):
    self.a = "a"

def change_type(self):
    self.a = 1

在实例化对象之前,self.a的类型是什么?如果需要内省,则不能使用python。

答案 1 :(得分:0)

我一直在对此进行一些研究,在某些情况下您可以可以执行此操作,但是还没有完美的解决方案:

  1. 如果您使用@property装饰符定义实例变量,那么在执行dir(class_type)时它将显示出来。
  2. 类似地,您可以使用__slots__魔术变量定义实例属性的允许列表,然后只需执行class_type.__slots__即可获取实例变量。
  3. 有点笨拙,但是您可以阅读该类的源代码,然后查找对self.varname = expression的任何引用。当然,这假设self将始终是引用类实例的方式,并且在诸如内部类或将self重新分配给另一个varname的情况下会失败。同样也不会选择setattr(self, varname, expression)之类的东西,您需要其他逻辑来进行检测。
  4. 可能比选项#3更健壮,您可以使用ast模块并将其用于解析类源代码。然后进行一些搜索以查找可能将属性写入类self的表达式。

查看此示例:

import dill, re

class Test:
    __slots__ = ["x","y","z"]
    def __init__(self):
        self.x = 0
        self.y = 1
        self.z = 2
    @property
    def q(self):
        return self.x

# this grabs those defined using __slots__ or @property
print(dir(Test))

# this looks at class source
# may need to play around with the regex more...
s = dill.source.getsource(Test)
var_finder = re.compile("self\.([^\W]+)\s*\=")
print(set(var_finder.findall(s)))

我个人认为在课堂上添加__slots__是最好的方法。对于sphinx文档(这是我的用例),这似乎是获取autosummary指令以提取这些实例变量的最佳方法。