Python相当于Java的getClass().getFields()

But*_*oni 5 python java reflection

我正在将一段代码从Java转换为Python,我不知道如何翻译以下内容:

Field[] fields = getClass().getFields();
    for (int i = 0; i < fields.length; i++ ) {
        if (fields[i].getName().startsWith((String) param){ ....
Run Code Online (Sandbox Code Playgroud)

csl*_*csl 9

在Python中,您可以查询对象的绑定__dict__,例如:

>>> class A:
...     def foo(self): return "bar"
...
>>> A.__dict__
{'__module__': '__main__', 'foo': <function foo at 0x7ff3d79c>, '__doc__': None}
Run Code Online (Sandbox Code Playgroud)

此外,这已经从C#的角度提出:如何在Python中枚举对象的属性?

__dict__您可以使用inspect.getmembers(object [,predicate])而不是直接使用,它具有类似的有用方法inspect.ismethod(object)

  • `inspect`模块是一个很好的建议.但是,我并不建议使用`__dict__`,因为一个对象的属性可以由`__slots__`定义.说,好答案:) (2认同)
  • 此外,属性不会出现在`__dict__`中,所以即使你没有使用`__slots__`,它也可能会破坏.无论如何,`inspect`模块负责所有这些. (2认同)

bra*_*zzi 7

首先,我要强调的是,getClass().getFields()在Python中没有这样的东西,因为一个对象可以有很多不是由类定义的字段.实际上,要在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
Run Code Online (Sandbox Code Playgroud)

所以,你没有得到一个类的字段.相反,您从对象获取字段.

此外,Python方法只是具有一些特殊值的字段.方法仅仅是函数的实例:

>>> type(foo.__init__)
Run Code Online (Sandbox Code Playgroud)

重要的是要注意,要明确表示getClass().getMethods()Python中没有这样的方法,并且"等效"也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']
Run Code Online (Sandbox Code Playgroud)

获得属性名称后,可以使用以下getattr()函数获取每个属性名称:

>>> getattr(foo, 'value')
42
Run Code Online (Sandbox Code Playgroud)

要获得所有这些,您可以使用列表推导:

>>> [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]
Run Code Online (Sandbox Code Playgroud)

最后,您可以找到在某些属性上设置的值.

但是,此列表也将包含方法.记住它们也是属性.在这种情况下,我们可以使列表理解避免可调用的属性:

>>> [attrname for attrname in dir(foo) if not callable(getattr(foo, attrname))]
['__dict__', '__doc__', '__module__', '__weakref__', 'another_value', 'value']
Run Code Online (Sandbox Code Playgroud)

现在,获取实际值:

>>> [getattr(foo, attrname) for attrname in dir(foo)
...      if not callable(getattr(foo, attrname))]
[{'another_value': 34, 'value': 42}, None, '__main__', None, 34, 42]
Run Code Online (Sandbox Code Playgroud)

那里仍然存在一些奇怪的值,例如__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]
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以做这些事情.例如,您可以查看对象的属性__dict____slots__属性.但是,我发现我提出的方法对于初学者来说更清晰.

编辑还有两点.首先,cls解决方案非常好,因为它建议你查看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)]
Run Code Online (Sandbox Code Playgroud)

幸运的是,cls建议的inspect.getmembers()函数做得更好.

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

要删除方法,只需避免使用callables:

>>> 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)]
Run Code Online (Sandbox Code Playgroud)

(不幸的是,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)]
Run Code Online (Sandbox Code Playgroud)

Python是一种非常动态的语言,在某些情况下,此解决方案无法正常工作.考虑到可能有一个对象应该存储一个在某处使用的函数.函数是可调用对象,不会显示该属性.但是,它在逻辑上是一个属性,即要使用的数据.你应该记住这种东西.但是,我打赌你不会经常得到这样的问题.

HTH


NPE*_*NPE 4

它并不完全等同,但dir(self)应该可以帮助您入门。