Question

(Quand je dis « adresse objet », je veux dire la chaîne que vous tapez en Python pour accéder à un objet. Par exemple 'life.State.step'. La plupart du temps, tous les objets avant le dernier point sera packages / modules, mais certains cas, ils peuvent être des classes ou d'autres objets.)

Dans mon projet Python J'ai souvent besoin de jouer avec des adresses d'objets. Certaines tâches que je dois faire:

  1. Étant donné un objet, obtenir son adresse.
  2. Étant donné une adresse, obtenir l'objet, l'importation des modules nécessaires sur le chemin.
  3. Raccourcir l'adresse d'un objet en se débarrassant des modules intermédiaires redondants. (Par exemple, 'life.life.State.step' peut être l'adresse officielle d'un objet, mais si les points de 'life.State.step' au même objet, je voudrais l'utiliser à la place parce qu'il est plus court.)
  4. Raccourcir l'adresse d'un objet par « enracinant » un module spécifié. (Par exemple, 'garlicsim_lib.simpacks.prisoner.prisoner.State.step' peut être l'adresse officielle d'un objet, mais je suppose que l'utilisateur sait où le paquet est prisoner, donc je veux utiliser 'prisoner.prisoner.State.step' comme adresse.)

Y at-il un module / cadre que les choses poignées comme ça? J'ai écrit quelques modules utilitaires pour faire ces choses, mais si quelqu'un a déjà écrit un module plus mature qui fait cela, je préfère utiliser.

Une note: S'il vous plaît, ne pas essayer de me montrer une mise en œuvre rapide de ces choses. Il est plus compliqué qu'il n'y paraît, il y a beaucoup de pièges, et tout code rapide n-sale va probablement échouer pour de nombreux cas importants. Ce genre de tâches appellent à un code bataille testé.

Mise à jour: Quand je dis "objet", je la plupart du temps des classes moyenne, modules, fonctions, méthodes, des choses comme celles-ci. Désolé de ne pas faire ce clair avant.

Était-ce utile?

La solution 2

Je libéré le module address_tools qui fait exactement ce que je demandais.

Voici le de code. Voici les essais .

Il fait partie de GarlicSim , vous pouvez donc l'utiliser par installation garlicsim et faire from garlicsim.general_misc import address_tools. Ses principales fonctions sont describe et resolve, qui sont parallèles à repr et eval. Les docstrings expliquent tout sur la façon dont fonctionnent ces fonctions.

Il y a même une version Python 3 sur le fourche Python 3 GarlicSim . Installez-le si vous voulez utiliser address_tools sur le code Python 3.

Autres conseils

Réponse courte: Non. Ce que vous voulez est impossible

La réponse longue est que ce que vous pensez que la « adresse » d'un objet est tout sauf. life.State.step est simplement l'une des façons d'obtenir une référence à l'objet à ce moment . Le même « adresse » à un stade ultérieur peut vous donner un autre objet, ou il pourrait être une erreur. De plus, cette « adresse » de vos dépend du contexte . En life.State.step, l'objet final ne dépend pas seulement de ce que life.State et life.State.step sont, mais quel objet le nom life fait référence dans cet espace de noms .

réponses spécifiques à vos demandes:

  1. L'objet final a aucune manière de savoir comment vous en avez parlé, et ni a un code que vous donnez l'objet. La « adresse » est pas un nom, ce n'est pas lié à l'objet, il est simplement une expression Python arbitraire qui se traduit par une référence d'objet (comme toutes les expressions font.) Vous ne pouvez effectuer ce travail, à peine , avec des objets spécifiques qui ne devraient pas se déplacer, comme des cours et des modules. Même si, ces objets peuvent se déplacer, et souvent faire se déplacer, donc ce que vous essayez est susceptible de se briser.

  2. Comme mentionné précédemment, la « adresse » dépend de beaucoup de choses, mais cette partie est assez facile: __import__() et getattr() peuvent vous donner ces choses. Ils seront toutefois extrêmement fragile, surtout quand il y a plus impliqué que le simple accès d'attribut. Il ne peut à distance le travail avec des choses qui sont dans les modules.

  3. "shortening" le nom nécessite l'examen tous les noms possibles , ce qui signifie tous les modules et tous les noms locaux, et tous les attributs d'entre eux , recrusively. Ce serait un très lent et fastidieux processus, et extrêmement fragile face à quoi que ce soit avec une méthode __getattr__ ou __getattribute__, ou avec des propriétés qui font plus que de retourner une valeur.

  4. est la même chose que 3.

Pour les points 3 et 4, je suppose que vous êtes à la recherche d'installations telles que

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

Cependant, ce n'est pas recommandé, car il rend plus difficile pour vous ou les gens qui lisent votre code de savoir rapidement ce que prisoner représente (où le module fait-il? Il faut regarder le début du code pour obtenir cette d'informations).

Pour le point 1, vous pouvez faire:

from uncertainties import UFloat

print UFloat.__module__  # prints 'uncertainties'

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

Pour le point 2, compte tenu de la chaîne « garlicsim_lib.simpacks.prisoner », vous pouvez obtenir l'objet auquel il se réfère à avec:

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

Cela suppose que vous avez importé le module avec

import garlicsim_lib  # or garlicsim_lib.simpacks

Si vous voulez même que cela soit automatique, vous pouvez faire quelque chose le long des lignes 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()

Cela ne fonctionne que dans les cas les plus simples (garlicsim_lib.simpacks doivent être disponibles dans garlicsim_lib, par exemple).

codage des choses de cette façon est cependant très rare.

Twisted a # 2 comme tordu / python / reflect.py. Vous avez besoin de quelque chose comme ça pour faire un système de configuration basée sur une chaîne, comme la configuration urls.py de Django.

Jetez un oeil sur le code et le journal de contrôle de version pour voir ce qu'ils avaient à faire pour le faire fonctionner - et ne parviennent! -. Le droit chemin

Les autres choses que vous recherchez assez des restrictions sur l'environnement Python qu'il n'y a pas une telle chose comme une solution à usage général.

de quelque chose de ici qui met en œuvre un peu votre # 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'
>>> 

Votre # 3 est sous-défini. Si je fais

__builtin__.step = path.to.your.stap

alors si le code de recherche trouver comme "étape"?

La simple mise en œuvre, je peux penser à des recherches simplement tous les modules et les regards des éléments de niveau supérieur qui sont exactement ce que vous voulez

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

Ici vous pouvez voir que « gestionnaire » a été fait dans _ du retour d'expression précédente, ce qui en fait le nom le plus court.

Si vous voulez quelque chose d'autre, comme la recherche récursive tous les membres de tous les modules, puis juste le code vers le haut. Mais comme l'exemple « _ » spectacles, il y aura des surprises. De plus, ce n'est pas stable, puisque l'importation d'un autre module pourrait faire un autre chemin d'objet disponible et plus court.

Voilà pourquoi les gens disent encore et encore que ce que vous voulez est pas vraiment utile pour quoi que ce soit, et qui est la raison pour laquelle il n'y a pas de modules pour elle.

Et comme pour votre # 4, comment dans le monde sera tout Cater paquet général à ces besoins de nommage?

Dans tous les cas, vous avez écrit

  

S'il vous plaît, ne pas essayer de me montrer un rapide   la mise en œuvre de ces choses. Ses   plus compliqué qu'il n'y paraît, il   sont beaucoup de gotchas, et tout   Code rapide n-sale probablement pas   pour de nombreux cas importants. Ce genre   des tâches pour le code testé appel-combat.

ne pense pas que mes exemples comme des solutions, mais à titre d'exemple des raisons pour lesquelles ce que vous demandez peu de sens. Il est un espace de solution fragile adn les rares qui s'y aventurent (surtout pour la curiosité) ont ces différentes préoccupations qu'une solution unique personnalisée est la meilleure chose. Un module pour la plupart d'entre eux n'a pas de sens, et si cela avait du sens l'explication de ce que le module ne serait probablement plus long que le code.

Et par conséquent, la réponse à votre question est « non, il n'y a pas de tels modules. »

Ce qui rend votre question encore plus déroutant est que la mise en œuvre de C de Python définit déjà une « adresse objet ». Les ( docs pour id) disent:

  

CPython détail de mise en œuvre. Ceci est l'adresse de l'objet

Qu'est-ce que vous cherchez est le nom ou le chemin de l'objet. Pas la "adresse objet Python."

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top