try que python inheritance python-2.7 introspection

que es try en python



¿Cuál es la forma correcta de anular el método__dir__? (3)

  1. y 3: si tu solución es correcta. recarray no define __dir__ simplemente porque la implementación por defecto estaba bien, por lo que no se molestaron en implementarla, y los numpy de numpy no diseñaron la clase para ser subclase, por lo que no veo por qué deberían haber molestado.

    A menudo es una mala idea crear subclases de tipos incorporados que no están diseñados específicamente para la herencia, por lo que le sugiero que utilice la delegación / composición en lugar de la herencia, excepto si hay una razón particular (por ejemplo, desea pasarla). a una función numpy que comprueba de forma isinstance con isinstance ).

  2. No. Como señalaste en python3, cambiaron la implementación para que haya un object.__dir__ , pero en otras versiones de python no puedo ver nada de lo que puedes hacer. Además, de nuevo, usar la recarray con herencia múltiple es simplemente una locura, las cosas se romperán. La herencia múltiple debe diseñarse con cuidado y, por lo general, las clases se diseñan específicamente para ser utilizadas con ella (por ejemplo, mezclas). Así que no me molestaría en tratar este caso, ya que quien lo intente será mordido por otros problemas.

    No veo por qué debería cuidar las clases que no tienen __dict__ ... ya que su subclase lo tiene, ¿cómo debería romperse? Cuando cambie la implementación de la subclase, por ejemplo, si usa __slots__ también podría cambiar fácilmente __dir__ . Si desea evitar la redefinición de __dir__ , simplemente puede definir una función que compruebe __dict__ luego __slots__ etc. Sin embargo, __slots__ cuenta que los atributos se pueden generar de forma sutil con __getattr__ y __getattribute__ y, por lo tanto, no puede capturarlos de forma confiable.

Esta pregunta pretende ser más sobre __dir__ que sobre numpy .

Tengo una subclase de numpy.recarray (en python 2.7, numpy 1.6.2), y noté que los nombres de los campos de recarray no aparecen en la lista al dirigir el objeto (y, por lo tanto, el autocompletado de ipython no funciona).

Tratando de arreglarlo, traté de reemplazar __dir__ en mi subclase, como esto:

def __dir__(self): return sorted(set( super(MyRecArray, self).__dir__() + / self.__dict__.keys() + self.dtype.fields.keys()))

que resultó con: AttributeError: ''super'' object has no attribute ''__dir__'' . (Encontré que esto debería funcionar en Python 3.3 ...)

Como solución, intenté:

def __dir__(self): return sorted(set( dir(type(self)) + / self.__dict__.keys() + self.dtype.fields.keys()))

Por lo que puedo decir, este funciona, pero por supuesto, no tan elegante.

Preguntas:

  1. ¿Es correcta la última solución en mi caso, es decir, para una subclase de recarray ?
  2. ¿Hay alguna manera de hacerlo funcionar en el caso general? Me parece que no funcionaría con herencia múltiple (rompiendo la cadena de super llamada) y, por supuesto, para objetos sin __dict__ ...
  3. ¿Sabe por qué recarray no admite enumerar sus nombres de campo para empezar? mero descuido?

Has probado:

def __dir__(self): return sorted(set( dir(super(MyRecArray, self)) + / self.__dict__.keys() + self.dtype.fields.keys()))


Python 2.7+, 3.3+ clase mezcla que simplifica la implementación del método __dir__ en las subclases. Espero que ayude. Gist

import six class DirMixIn: """ Mix-in to make implementing __dir__ method in subclasses simpler """ def __dir__(self): if six.PY3: return super(DirMixIn, self).__dir__() else: # code is based on # http://www.quora.com/How-dir-is-implemented-Is-there-any-PEP-related-to-that def get_attrs(obj): import types if not hasattr(obj, ''__dict__''): return [] # slots only if not isinstance(obj.__dict__, (dict, types.DictProxyType)): raise TypeError("%s.__dict__ is not a dictionary" "" % obj.__name__) return obj.__dict__.keys() def dir2(obj): attrs = set() if not hasattr(obj, ''__bases__''): # obj is an instance if not hasattr(obj, ''__class__''): # slots return sorted(get_attrs(obj)) klass = obj.__class__ attrs.update(get_attrs(klass)) else: # obj is a class klass = obj for cls in klass.__bases__: attrs.update(get_attrs(cls)) attrs.update(dir2(cls)) attrs.update(get_attrs(obj)) return list(attrs) return dir2(self)