Python中与Java的getClass().getFields()相对应的方法是什么?

6
我正在将一段Java代码转换为Python,但我不知道如何翻译以下内容:
Field[] fields = getClass().getFields();
    for (int i = 0; i < fields.length; i++ ) {
        if (fields[i].getName().startsWith((String) param){ ....

我不确定 getClass().getFields() 是什么意思,但你看过 dir 吗?a = myClass() dir(a) - inspectorG4dget
3个回答

8
在Python中,您可以使用__dict__查询对象的绑定,例如:
>>> class A:
...     def foo(self): return "bar"
...
>>> A.__dict__
{'__module__': '__main__', 'foo': <function foo at 0x7ff3d79c>, '__doc__': None}

此外,这个问题也从C#角度提出过:如何在Python中枚举一个对象的属性?

你可以使用inspect.getmembers(object[, predicate])代替直接使用__dict__。该方法有一些有用的函数,例如inspect.ismethod(object)


2
“inspect” 模块是一个很好的建议。然而,我不建议玩弄 __dict__,因为一个对象可以通过 __slots__ 定义其属性。话虽如此,回答不错 :) - brandizzi
2
另外,属性不会显示在__dict__中,因此即使您没有使用__slots__,它也很可能会出现问题。无论如何,inspect模块会处理所有这些问题。 - Joe Kington

8
首先,我想强调的是在Python中不存在getClass().getFields()这样的东西,因为一个对象可能有很多不是由类定义的字段。实际上,在Python中创建字段只需要给它赋值即可。这些字段不是被定义的,而是被创建的:
>>> class Foo(object):
...     def __init__(self, value):
...         # The __init__ method will create a field
...         self.value = value
... 
>>> foo = Foo(42)
>>> foo.value
42
>>> # Accessing inexistent field
... foo.another_value
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
AttributeError: 'Foo' object has no attribute 'another_value'
>>> # Creating the field
... foo.another_value = 34
>>> # Now I can use it
... foo.another_value
34

所以,你不能从一个类中获取字段。相反,你需要从一个对象中获取字段。
此外,Python方法只是带有一些特殊值的字段。方法只是函数的实例:
>>> type(foo.__init__)

重要的是要注意,Python 中不存在 getClass().getMethods() 这样的方法,而 getClass().getFields() 的“等效”将返回方法。
话虽如此,你如何获取字段(或在 Python 中经常称为属性)?当然你不能从类中获取它们,因为对象存储它们。因此,你可以使用 dir() 函数获取对象的属性名称。
>>> dir(foo)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
 '__getattribute__', '__hash__', '__init__', '__module__', '__new__', 
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', 
 '__str__', '__subclasshook__', '__weakref__', 'another_value', 'value']

一旦你获得了属性名称,你可以使用 getattr() 函数来获取每个属性:
>>> getattr(foo, 'value')
42

要获取它们全部,您可以使用列表推导式
>>> [getattr(foo, attrname) for attrname in dir(foo)]
[<class '__main__.Foo'>, <method-wrapper '__delattr__' of Foo object at 0x2e36b0>,
 {'another_value': 34, 'value': 42}, None, <built-in method __format__ of Foo object at 0x2e36b0>, 
 <method-wrapper '__getattribute__' of Foo object at 0x2e36b0>, 
 ... # Lots of stuff
 34, 42]

在最后,您可以找到一些属性上设置的值。
然而,这个列表也会包含方法。请记住,它们也是属性。在这种情况下,我们可以让列表推导式避免可调用属性:
>>> [attrname for attrname in dir(foo) if not callable(getattr(foo, attrname))]
['__dict__', '__doc__', '__module__', '__weakref__', 'another_value', 'value']

现在,获取实际值:
>>> [getattr(foo, attrname) for attrname in dir(foo)
...      if not callable(getattr(foo, attrname))]
[{'another_value': 34, 'value': 42}, None, '__main__', None, 34, 42]

还有一些奇怪的值,比如__dict____doc__等等。它们是你可能想要忽略的一些东西。如果是这样,只需在列表推导式中加入另一个条件:

>>> [attrname for attrname in dir(foo)
...     if not attrname.startswith('__') and
...         not callable(getattr(foo, attrname))]
['another_value', 'value']
>>> [getattr(foo, attrname) for attrname in dir(foo)
...     if not attrname.startswith('__') and
...         not callable(getattr(foo, attrname))]
[34, 42]

有其他方法可以完成这样的事情。例如,您可以查看对象的__dict____slots__属性。但是,我发现我提供的方法对于初学者来说更清晰。

编辑 另外两点。首先,cls solution非常好,因为它建议您查看inspect模块

此外,您可能希望获取属性的名称和值。您可以生成一个元组列表来获取它:

>>> [(attrname, getattr(foo, attrname)) for attrname in dir(foo)
...     if not attrname.startswith('__') and
...         not callable(getattr(foo, attrname))]
[('another_value', 34), ('value', 42)]

幸运的是,cls建议使用inspect.getmembers()函数可以更好地完成此任务。

>>> import inspect
>>> inspect.getmembers(foo)
[('__class__', <class '__main__.Foo'>),
 # ... Lots of stuff ...
 ('another_value', 34), ('value', 42)]

要删除方法,只需避免可调用对象:

>>> inspect.getmembers(foo, lambda attr: not callable(attr))
[('__dict__', {'another_value': 34, 'value': 42}), ('__doc__', None), ('__module__', '__main__'), ('__weakref__', None), ('another_value', 34), ('value', 42)]

遗憾的是,inspect.ismethod()并没有像我预期的那样工作。

因为有许多内部内容,我们无法像处理方法那样直接获取它们。但是这并不是问题,可以再次使用列表推导式解决:

>>> [(name, value) for name, value in inspect.getmembers(foo, lambda attr: not callable(attr))
...         if not name.startswith('__')]
[('another_value', 34), ('value', 42)]

Python是一种非常动态的语言,因此这个解决方案在某些情况下可能无法很好地工作。考虑到可能会有一个对象,应该存储一个要在其他地方使用的函数。函数是可调用对象,属性将不会被呈现。但是,它在逻辑上是一个属性,一个要使用的数据。你应该记住这种东西。然而,我敢打赌你不会太频繁遇到这样的问题。
希望对你有所帮助。

4

这不是完全等价的,但dir(self)应该能帮你开始。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接