Pregunta

(Cuando digo "dirección de objeto", me refiero a la cadena que ha escrito en Python para acceder a un objeto. Por ejemplo 'life.State.step'. La mayor parte del tiempo, todos los objetos antes del último punto habrá paquetes / módulos, pero en algunos casos también pueden ser clases u otros objetos.)

Python proyecto A menudo tengo la necesidad de jugar con direcciones de objetos. Algunas de las tareas que tienen que hacer:

  1. Dado un objeto, obtener su dirección.
  2. Dada una dirección, obtener el objeto, la importación de todos los módulos necesarios en el camino.
  3. Dirección Acortar un objeto de al deshacerse de los módulos intermedios redundantes. (Por ejemplo, 'life.life.State.step' puede ser la sede social de un objeto, pero si puntos 'life.State.step' al mismo objeto, que me gustaría usarlo en lugar porque es más corta.)
  4. Dirección Acortar una de objeto "enraizamiento" de un módulo especificado. (Por ejemplo, 'garlicsim_lib.simpacks.prisoner.prisoner.State.step' puede ser la sede social de un objeto, pero supongo que el usuario sabe dónde está el paquete de prisoner es, por lo que me gustaría utilizar 'prisoner.prisoner.State.step' como la dirección.)

¿Hay un módulo / marco que se encarga de cosas por el estilo? Escribí un par de módulos de servicios públicos para hacer estas cosas, pero si alguien ya ha escrito un módulo que tiene esto, yo prefiero usar ese más maduro.

Una nota: Por favor, no trate de mostrarme una rápida implementación de estas cosas. Es más complicado de lo que parece, hay un montón de trampas y cualquier código sucia rápida-n-probablemente fallará durante muchos casos importantes. Este tipo de tareas requiere un código de batalla probado.

ACTUALIZACIÓN: Cuando digo "objeto", que en su mayoría media clases, módulos, funciones, métodos, cosas como éstas. Lo siento por no hacer esto claro antes.

¿Fue útil?

Solución 2

Me lanzó el módulo address_tools que hace exactamente lo que pedí.

Aquí está el código . Aquí están las pruebas .

Es parte de GarlicSim , por lo que se puede utilizar por instalación garlicsim y haciendo from garlicsim.general_misc import address_tools. Sus principales funciones son describe y resolve, que son paralelas a repr y eval. Las cadenas de documentación explican todo acerca de cómo estas funciones de trabajo.

Hay incluso una versión de Python 3 en el Python 3 tenedor de GarlicSim . Instalarlo si desea utilizar address_tools el código Python 3.

Otros consejos

Breve respuesta:. No. Lo que queremos es imposible

La respuesta larga es que lo que piensa de que la "dirección" de un objeto es todo lo contrario. life.State.step no es más que una de las maneras de obtener una referencia al objeto en ese momento . La misma "dirección" en un momento posterior le puede dar un objeto diferente, o podría ser un error. Lo que es más, esta "dirección" de los suyos depende del contexto . En life.State.step, el objeto final depende no sólo de lo que life.State y life.State.step son, pero lo que se opone el nombre life se refiere en ese espacio de nombres .

respuestas específicas a sus peticiones:

  1. El objetivo final tiene ninguna manera en absoluto de averiguar cómo se dirige a él, y tampoco tiene ningún código que le da al objeto a. La "dirección" no es un nombre, no está atado al objeto, es meramente una expresión Python arbitrario que resulta en una referencia de objeto (como todas las expresiones hacen.) Sólo se puede hacer este trabajo, Apenas , con objetos específicos que no se espera para moverse, como las clases y módulos. Aun así, esos objetos pueden moverse, y con frecuencia lo moverse, así que lo que se intenta es probable que se rompa.

  2. Como se ha mencionado, la "dirección" depende de muchas cosas, pero esta parte es bastante fácil: __import__() y getattr() le pueden dar estas cosas. Ellos, sin embargo, ser extremadamente frágil, sobre todo cuando hay más complicado que simplemente el acceso atributo. Sólo puede trabajar a distancia con las cosas que están en los módulos.

  3. "acortamiento" el nombre requiere examinar todos los nombres posibles , es decir, todos los módulos y todos los nombres locales, y todos los atributos de ellos , recrusively. Sería una.

  4. muy lento y laborioso proceso, y extremadamente frágil en la cara de cualquier cosa con un método __getattr__ o __getattribute__, o con propiedades que hacen más que un valor de retorno
  5. es el mismo que 3.

Para los puntos 3 y 4, supongo que usted está buscando instalaciones como

from life import life  # life represents life.life
from garlicsim_lib.simpacks import prisoner

Sin embargo, esto no es recomendable, ya que hace que sea más difícil para usted o las personas que leen el código para saber rápidamente lo prisoner representa (donde funciona el módulo viene? Usted tiene que mirar en el principio del código para obtener esta información).

En el punto 1, que puede hacer:

from uncertainties import UFloat

print UFloat.__module__  # prints 'uncertainties'

import sys
module_of_UFloat = sys.modules[UFloat.__module__]

En el punto 2, dada la cadena 'garlicsim_lib.simpacks.prisoner', se puede obtener el objeto que se refiere a con:

obj = eval('garlicsim_lib.simpacks.prisoner')

Esto supone que ha importado el módulo con

import garlicsim_lib  # or garlicsim_lib.simpacks

Si aún desea que esto sea automático, puede hacer algo en la línea de

import imp

module_name = address_string.split('.', 1)[0]
mod_info = imp.find_module(module_name)
try:
    imp.load_module(module_name, *mod_info)
finally:
    # Proper closing of the module file:
    if mod_info[0] is not None:
        mod_info[0].close()

Esto funciona sólo en los casos más simples (necesidad garlicsim_lib.simpacks que esté disponible en garlicsim_lib, por ejemplo).

Codificación de las cosas de esta manera es, sin embargo, muy poco habitual.

Twisted tiene # 2 como torcido / Python / reflect.py. Es necesario algo parecido para la fabricación de un sistema de configuración basado en cadena, al igual que con la configuración urls.py de Django.

Tome un vistazo al código y el registro de control de versiones para ver lo que tenían que hacer para que funcione - y fallan! -. La manera correcta

Las otras cosas que usted está buscando lugar lo suficientemente restricciones en el entorno de Python que no hay tal cosa como una solución de propósito general.

A continuación de algo que pone en práctica un tanto su # 1

>>> import pickle
>>> def identify(f):
...   name = f.__name__
...   module_name = pickle.whichmodule(f, name)
...   return module_name + "." + name
... 
>>> identify(math.cos)
'math.cos'
>>> from xml.sax.saxutils import handler
>>> identify(handler)
'__main__.xml.sax.handler'
>>> 

Su # 3 se underdefined. Si hago

__builtin__.step = path.to.your.stap

A continuación, debe encontrar el código de búsqueda como "paso"?

La implementación más simple que puedo pensar simplemente busca en todos los módulos y las miradas de elementos de nivel superior que son exactamente lo que quiere

>>> import sys
>>> def _find_paths(x):
...   for module_name, module in sys.modules.items():
...     if module is None:
...         continue
...     for (member_name, obj) in module.__dict__.items():
...       if obj is x:
...         yield module_name + "." + member_name
... 
>>> def find_shortest_name_to_object(x):
...   return min( (len(name), name) for name in _find_paths(x) )[1]
... 
>>> find_shortest_name_to_object(handler)
'__builtin__._'
>>> 5
5
>>> find_shortest_name_to_object(handler)
'xml.sax.handler'
>>> 

Aquí se puede ver que 'manipulador' fue realmente en _ desde el retorno expresión anterior, por lo que es el nombre más corto.

Si quieres algo más, como la búsqueda de forma recursiva todos los miembros de todos los módulos, a continuación, sólo código de arriba. Pero a medida que los "_" ejemplo muestra, habrá sorpresas. Además, esto no es estable, ya que la importación de otro módulo podría hacer otra ruta de objeto disponible y más corto.

Es por eso que la gente dice una y otra vez que lo que quiere no es realmente útil para cualquier cosa, y es por eso que no hay módulos para ello.

Y en cuanto a su # 4, cómo en el mundo va a atender cualquier paquete en general a esas necesidades de nomenclatura?

En cualquier caso, usted escribió

  

Por favor, no trate de mostrarme una rápida   implementación de estas cosas. Sus   más no complicado de lo que parece,   un montón de trampas, y cualquier   código rápido-n-sucia probablemente fallará   desde hace muchos casos importantes. Este tipo   tareas de llamar para el código probado en combate.

así que no creo que de mis ejemplos como soluciones, sino como ejemplos de por qué lo que está pidiendo no tiene mucho sentido. Es un espacio de soluciones frágiles tales adn de los pocos que hay riesgo (en su mayoría por curiosidad) tienen tales preocupaciones diferentes que una solución de una sola vez la costumbre es lo mejor. Un módulo para la mayoría de ellos no tiene sentido, y si tenía sentido la explicación de lo que el módulo no sería probablemente más largo que el código.

Y por lo tanto, la respuesta a su pregunta es "no, no hay tales módulos."

Lo que hace que su pregunta aún más confuso es que la implementación en C de Python ya se define una "dirección de objeto". Los de Identificación () dicen:

  

detalle de implementación CPython:. Esta es la dirección del objeto

Lo que estamos buscando es el nombre o la ruta de acceso al objeto. No es la "dirección de objeto Python."

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top