繁体   English   中英

Python 类实例自省

[英]Python class instances introspection

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

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

class Sub(Super):
    pass

a = Super("Nice_Name")

print(a.__dict__.keys())

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

不,你不能,因为 python 不是静态类型语言,所以在实例化对象之前,该对象没有类型。 例如,想象一个这样的类:

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

def change_type(self):
    self.a = 1

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

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

  1. 如果您使用@property装饰器定义实例变量,那么它会在执行dir(class_type)
  2. 同样,您可以使用__slots__魔术变量定义允许的实例属性列表,然后只需执行class_type.__slots__即可获取您的实例变量。
  3. 有点hacky,但您可以阅读该类的源代码,然后查找对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指令获取这些实例变量的最佳方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM