2011-05-26 23 views
5

Estoy convertir un trozo de código de Java a Python y no sé cómo traducir lo siguiente:Python equivalente de getClass de Java() getFields()

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

No estoy seguro de lo que 'getClass(). GetFields()' hace, pero ¿ha mirado 'dir'? 'a = myClass()' 'dir (a)' – inspectorG4dget

Respuesta

3

No es un equivalente exacto , pero dir(self) debería comenzar.

9

En Python, puede consultar las consolidaciones de un objeto con __dict__, por ejemplo:

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

Además, esto se ha preguntado de un # punto de vista C en: How to enumerate an object's properties in Python?

En lugar de utilizar __dict__ directamente, puede use inspect.getmembers(object[, predicate]), que tiene métodos útiles como inspect.ismethod(object)

+2

El módulo 'inspect' es una gran sugerencia. Sin embargo, no recomendaría jugar con '__dict__', ya que un objeto puede tener sus atributos definidos por' __slots__'. Dijo que, buena respuesta :) – brandizzi

+2

Además, las propiedades no aparecen en '__dict__', por lo que incluso si no estás usando' __slots__', es probable que se rompa. De todos modos, el módulo 'inspeccionar' se ocupa de todo eso. –

6

En primer lugar, enfatizo que no existe tal cosa como getClass().getFields() en Python porque un ob ject puede tener muchos campos que no están definidos por clase. En realidad, para crear un campo en Python solo necesita atribuirle un valor. Los campos no están definidos , la son creados:

>>> 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 

Por lo tanto, usted no consigue los campos de una clase. En cambio, obtienes los campos de un objeto.

Además, los métodos de Python son solo campos con algunos valores especiales. Los métodos son meramente ejemplos de funciones:

>>> type(foo.__init__) 

Es importante señalar que para que quede claro que no existe un método tal como getClass().getMethods() en Python y el "equivalente" de getClass().getFields() volverá métodos, así .

Dijo que, ¿cómo podría obtener los campos (o atributos, como se llaman con frecuencia en Python)? Por supuesto, no puedes obtenerlos de la clase, ya que los objetos los almacenan. Para que pueda obtener el nombre de los atributos de un objeto utilizando la función 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'] 

Una vez que tienes los nombres de atributo, puede obtener cada uno de ellos mediante el uso de la función getattr():

>>> getattr(foo, 'value') 
42 

para obtener todos ellos, se puede utilizar list comprehensions:

>>> [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] 

a finales , puede encontrar los valores que establece en algunos atributos.

Sin embargo, esta lista también incluirá métodos. Recuerde que son atributos también.En este caso, podemos hacer nuestros attrbutes exigibles lista por comprensión evitar:

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

Ahora, conseguir los valores reales:

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

Todavía hay algunos valores extraños allí, como __dict__, __doc__ etc. Son algunas cosas que quizás quieras ignorar. Si es así, simplemente ponga otro criterio en su lista de comprensión:

>>> [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] 

Hay otras maneras de hacer tales cosas. Por ejemplo, puede buscar los atributos __dict__ y __slots__ de un objeto. Sin embargo, creo que el método que he presentado es más claro para los principiantes.

EDIT Dos puntos más. Primero, el cls solution es realmente bueno porque sugiere que mire el inspect module.

Además, es posible que desee obtener el nombre y el valor de un atributo. Se puede conseguir la generación de una lista de tuplas:

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

Afortunadamente, la función inspect.getmembers() sugerido por cls lo hace mejor.

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

Para eliminar métodos, simplemente evita 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)] 

(Por desgracia, no inspect.ismethod() no funcionó como esperaba.)

Hay un montón de cosas internas todavía y no se puede salir directamente, como lo hicimos con los métodos. Nada de lo que una lista por comprensión puede resolver de nuevo:

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

Python es un lenguaje muy dinámico y esta solución no puede funcionar tan bien en algunos casos. Considere que es posible tener un objeto que debería ser utilizado para almacenar una función en alguna parte. Una función es un objeto invocable y el atributo no se presentará. Sin embargo, es lógicamente un atributo, un dato a ser utilizado. Deberías tener este tipo de cosas en mente. Sin embargo, apuesto a que no tendrás esos problemas con demasiada frecuencia.

HTH