有没有一种方法可以在不实例化对象的情况下列出类的属性?

vwr*_*bel 24 python python-3.x

在Python 3.5中,说我有:

class Foo:
    def __init__(self, bar, barbar):
        self.bar = bar
        self.barbar = barbar
Run Code Online (Sandbox Code Playgroud)

我想["bar", "barbar"]从课堂上获取列表.

我知道我能做到:

foo = Foo(1, 2)
foo.__dict__.keys()
Run Code Online (Sandbox Code Playgroud)

有没有办法在["bar", "barbar"] 没有实例化对象的情况下获得?

Lær*_*rne 26

不,因为属性是动态的(所谓的实例属性).考虑以下,

class Foo:
    def __init__( self ):
        self.bar = 1

    def twice( self ):
        self.barbar = 2

f = Foo()
print( list(f.__dict__.keys() ) )
f.twice()
print( list(f.__dict__.keys() ) )
Run Code Online (Sandbox Code Playgroud)

在第一次打印中,仅f.bar设置了,因此这是打印属性键时显示的唯一属性.但是在调用之后f.twice(),你创建一个新的属性f,现在打印它显示barbarbar.

  • 你可能想要考虑带有`__slots__`的类可能是一个例外. (2认同)

idj*_*jaw 10

警告 - 始终提供100%正确的数据以下并非万无一失.如果你最终不得不像self.y = int(1)你的__init__,你最终会包括int你的属性的集合,这是不是你的目标通缉结果英寸 此外,如果您碰巧在代码中的某处添加动态属性Foo.some_attr = 'pork',那么您将永远不会看到它.请注意您在检查代码的哪一点时所做的是什么,并了解您为什么会在结果中包含这些包含内容.可能还有其他"破损"不能让你完全100%期望与这个相关的所有属性,但是,下面的内容应该会给你一些你可能正在寻找的东西.

但是,我强烈建议您在此处获取其他答案的建议以及标记的副本,以解释为什么您不能/不应该这样做.

以下是您可以尝试解决的一种解决方案:

我将扩大inspect答案.

但是,我确实(并且可能会建议反对)在生产代码中执行类似这样的操作的有效性.出于调查目的,一定要把自己打倒.

通过使用其他一个答案中已指示的检查模块,您可以使用getmembers方法,然后您可以迭代这些属性并检查您要调查的相应数据.

例如,您正在质疑动态属性 __init__

因此,我们可以用这个例子来说明:

from inspect import getmembers


class Foo:
    def __init__(self, x):
        self.x = x
        self.y = 1
        self.z = 'chicken'


members = getmembers(Foo)

for member in members:
    if '__init__' in member:
        print(member[1].__code__.co_names)
Run Code Online (Sandbox Code Playgroud)

你的输出将是一个元组:

('x', 'y', 'z')
Run Code Online (Sandbox Code Playgroud)

最后,当您检查类Foo以获取其成员时,您可以在迭代每个成员时进一步调查这些属性.每个成员都有进一步检查的属性,依此类推.对于这个特定的例子中,我们集中在__init__检查__code__(每个文档:该__code__对象表示编译函数体)属性,它具有称为属性co_names上面运行的代码的输出所指示的,其提供构件的元组.