Domanda

(Quando dico "indirizzo oggetto", voglio dire la stringa che si digita in Python per accedere a un oggetto. Per esempio 'life.State.step'. La maggior parte del tempo, tutti gli oggetti prima che l'ultimo punto sarà pacchetti / moduli, ma in alcuni casi possono essere classi o altri oggetti.)

Nel mio Python progetto ho spesso la necessità di giocare con gli indirizzi degli oggetti. Alcune attività che hanno a che fare:

  1. Dato un oggetto, ottenere il suo indirizzo.
  2. Dato un indirizzo, ottenere l'oggetto, l'importazione di tutti i moduli necessari sulla strada.
  3. indirizzo Shorten un oggetto da sbarazzarsi di moduli intermedi ridondanti. (Per esempio, 'life.life.State.step' può essere l'indirizzo ufficiale di un oggetto, ma se i punti 'life.State.step' allo stesso oggetto, avrei voluto usarlo al posto perché è più breve.)
  4. indirizzo Shorten un oggetto da "radicamento" un modulo specificato. (Per esempio, 'garlicsim_lib.simpacks.prisoner.prisoner.State.step' può essere l'indirizzo ufficiale di un oggetto, ma suppongo che l'utente sa dove il pacchetto prisoner è, quindi mi piacerebbe voglio usare 'prisoner.prisoner.State.step' come indirizzo.)

C'è un modulo / framework che gestisce cose del genere? Ho scritto un paio di moduli di utilità per fare queste cose, ma se qualcuno ha già scritto un più maturo modulo che fa questo, preferirei usare quella.

Una nota: Per favore, non cercate di farmi vedere una rapida attuazione di queste cose. E 'più complicato di quanto sembri, ci sono un sacco di trucchi, e qualsiasi codice quick-n-sporco probabilmente fallirà per molti casi importanti. Questo tipo di attività di chiamata per il codice battaglia-testato.

UPDATE: Quando dico "oggetto", Io per lo più medio classi, moduli, funzioni, metodi, cose come queste. Mi spiace di non aver chiarito questo punto prima.

È stato utile?

Soluzione 2

I rilasciato il modulo address_tools che fa esattamente quello che ho chiesto.

Ecco il codice . Qui ci sono le prove di .

E 'parte di di GarlicSim , in modo da poter utilizzare per l'installazione garlicsim e facendo from garlicsim.general_misc import address_tools. Le sue funzioni principali sono describe e resolve, che sono parallele e repr eval. I docstrings spiegano tutto su come queste funzioni di lavoro.

C'è anche una versione di Python 3 sul Python 3 fork di GarlicSim . Installarlo se si desidera utilizzare address_tools il codice Python 3.

Altri suggerimenti

Risposta breve:. No. Quello che si vuole è impossibile

La risposta lunga è che cosa ne pensi di come il "indirizzo" di un oggetto è tutt'altro. life.State.step è solo uno dei modi per ottenere un riferimento all'oggetto in quel particolare momento . Lo stesso "indirizzo" in un momento successivo può dare un oggetto diverso, o potrebbe essere un errore. Cosa c'è di più, questo "indirizzo" del tuo dipende dal contesto . Nel life.State.step, l'oggetto finale non dipende solo su ciò che life.State e life.State.step sono, ma quello oggetto il nome si riferisce a life in quel namespace .

risposte specifiche alle vostre richieste:

  1. L'oggetto finale ha maniera più assoluta di scoprire come lei ha fatto riferimento ad esso, e nessuno dei due ha alcun codice che ti danno l'oggetto. L ' "indirizzo" non è un nome, non è legata all'oggetto, è solo espressione arbitraria Python che si traduce in un riferimento a un oggetto (come tutte le espressioni fanno.) Si può fare solo questo lavoro, malapena , con oggetti specifici che si prevede non muoversi, come le classi e moduli. Anche così, quegli oggetti possono muoversi, e spesso do muoversi, così quello che si cerca è probabile rompere.

  2. Come accennato, il "indirizzo" dipende da molte cose, ma questa parte è abbastanza facile: __import__() e getattr() può dare queste cose. Essi, tuttavia, essere estremamente fragile, soprattutto quando c'è più coinvolto non solo l'accesso attributo. Si può solo lontanamente lavoro con le cose che sono in moduli.

  3. "accorciamento", il nome richiede un esame ogni nome possibile , cioè tutti i moduli e tutti i nomi locali, e tutti gli attributi di loro , recrusively. Sarebbe una.

  4. molto lento e lungo processo, ed estremamente fragile di fronte a qualsiasi cosa con un metodo __getattr__ o __getattribute__, o con proprietà che fanno più che restituiscono un valore
  5. è la stessa cosa di 3.

Per i punti 3 e 4, immagino che siete alla ricerca di servizi come

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

Tuttavia, questo non è consigliato, in quanto rende più difficile per voi o persone che leggono il codice per sapere rapidamente ciò che prisoner rappresenta (in cui il modulo proviene? Si deve guardare all'inizio del codice per ottenere questo informazioni).

Per il punto 1, si può fare:

from uncertainties import UFloat

print UFloat.__module__  # prints 'uncertainties'

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

Per il punto 2, dando la stringa 'garlicsim_lib.simpacks.prisoner', si può ottenere l'oggetto si riferisce con:

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

Questo suppone che avete importato il modulo con

import garlicsim_lib  # or garlicsim_lib.simpacks

Se anche desidera che questo sia automatica, si può fare qualcosa sulla falsariga di

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

Questo funziona solo nei casi più semplici (garlicsim_lib.simpacks necessità di essere disponibile in garlicsim_lib, per esempio).

Codifica cose in questo modo, tuttavia, è molto inusuale.

ritorto ha # 2 come contorto / python / reflect.py. Hai bisogno di qualcosa di simile per fare un sistema di configurazione basato sulle stringhe, come con la configurazione urls.py di Django.

Date un'occhiata al codice e il registro di controllo delle versioni per vedere quello che dovevano fare per farlo funzionare - e non riescono! -. La strada giusta

Le altre cose che state cercando per le restrizioni spazio sufficiente per l'ambiente Python che non esiste una cosa come una soluzione di uso generale.

È qui qualcosa che implementa un po 'il vostro # 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'
>>> 

Il # 3 è underdefined. Se faccio

__builtin__.step = path.to.your.stap

quindi se il codice di ricerca trovarlo come "passo"?

L'applicazione più semplice che posso pensare semplicemente cerca tutti i moduli e cerca elementi di livello superiore, che sono esattamente quello che vuoi

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

Qui si può vedere che 'handler' stato effettivamente in _ dal precedente ritorno espressione, il che rende il nome più breve.

Se si desidera qualcosa di diverso, come la ricerca in modo ricorsivo tutti i membri di tutti i moduli, quindi solo il codice in su. Ma, come i "_" esempio mostra, ci saranno sorprese. Inoltre, questo non è stabile, dal momento che l'importazione di un altro modulo potrebbe fare un altro percorso dell'oggetto disponibili e più breve.

È per questo che la gente dice più e più volte che ciò che si vuole non è effettivamente utile per qualsiasi cosa, ed è per questo non c'è moduli per esso.

E per quanto riguarda il vostro # 4, come in tutto il mondo sarà qualsiasi pacchetto cater generale a quei bisogni di denominazione?

In ogni caso, è scritto

  

Per favore, non cercate di farmi vedere un rapido   attuazione di queste cose. Suo   più complicato di quanto possa sembrare, ci   sono un sacco di trucchi, e qualsiasi   Codice rapido-n-sporco probabilmente fallirà   per molti casi importanti. Questo tipo   di compiti chiamare per il codice battaglia-testato.

in modo da non penso dei miei esempi come soluzioni, ma come esempi del perché quello che stai chiedendo ha poco senso. Si tratta di una soluzione di tale spazio fragile adn i pochi che ci venture (per lo più per curiosità) hanno tali preoccupazioni diverse che una soluzione una tantum personalizzati è la cosa migliore. Un modulo per la maggior parte di questi non ha senso, e se ha senso la spiegazione di ciò che il modulo non sarebbe probabilmente più lungo del codice.

E quindi la risposta alla tua domanda è "no, non ci sono tali moduli."

Ciò che rende la tua domanda ancora più confusa è che l'implementazione in C di Python definisce già un "indirizzo oggetto". I documentazione per id () dicono:

  

CPython dettaglio di implementazione:. Questo è l'indirizzo dell'oggetto

Quello che stai cercando è il nome, o il percorso all'oggetto. Non il "indirizzo oggetto Python".

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top