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

时间:2017-06-12 13:36:36

标签: python python-3.x

在Python 3.5中,我说:

class Foo:
    def __init__(self, bar, barbar):
        self.bar = bar
        self.barbar = barbar

我希望从课程中获取列表["bar", "barbar"]

我知道我能做到:

foo = Foo(1, 2)
foo.__dict__.keys()

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

3 个答案:

答案 0 :(得分: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() ) )

在第一次打印中,只设置了f.bar,这是打印属性键时显示的唯一属性。但在致电f.twice()后,您为f创建属性,现在打印它会显示barbarbar

答案 1 :(得分:10)

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

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

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

我将扩展inspect答案。

但是,我在生产 -ready代码中做了类似的事情的问题(并且可能会建议反对)。出于调查目的,一定要把自己打倒。

通过使用其他一个答案中已指明的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)

您的输出将是一个元组:

('x', 'y', 'z')

最终,当您检查类Foo以获取其成员时,您可以在迭代每个成员时进一步调查这些属性。每个成员都有进一步检查的属性,依此类推。对于此特定示例,我们专注于__init__检查 __code__(每个文档:表示已编译函数体的__code__对象)属性,该属性具有属性名为co_names,它提供了如上所示的成员元组以及运行代码的输出。

答案 2 :(得分:-6)

正如Lærne所提到的,在函数内部声明的属性(如__init__)是动态的。在调用__init__函数之前,它们实际上不存在

然而,有一种方法可以做你想要的。

您可以创建 class 属性,如下所示:

class Foo:
    bar = None
    barbar = None

    def __init__(self, bar, barbar):
        self.bar = bar
        self.barbar = barbar

你可以访问这些属性:

[var for var in vars(Foo).keys() if not var.startswith('__')]

这给出了这个结果:

['bar', 'barbar']