2012-06-13 16 views
8

Esiste una funzione nella libreria standard Python per riprodurre lo schema di mangling dei nomi di Python con un nome di attributo "privato"? Sembra che ci sarebbe, ma non riesco a trovarlo per la vita di me.Funzione di mangling nome Python

Ho scritto questo, ma se c'è un modo migliore sono tutto orecchie.

def mangle_name (cls, attrname) : 
    prefix = '_' + cls.__name__.lstrip('_') 

    if not attrname.startswith('__') : 
     attrname = '__' + attrname 

    if not attrname.endswith('__') : 
     return prefix + attrname 
    else : 
     return attrname 

class Foo : 
    __some_such = 3 

name = mangle_name(Foo, '__some_such') 
print name 
print hasattr(Foo(), name) 
+3

Sono abbastanza sicuro che non v'è alcuna funzione nel libreria standard. A cosa ti serve? –

+8

Posso immaginare che questo sarà quasi sempre usato per fare qualcosa di male. –

+0

Fondamentalmente, ho bisogno di accedere in modo dinamico agli attributi privati ​​di una classe arbitraria. La funzione sopra funziona; tuttavia, potrebbero esserci problemi di cui non sono a conoscenza (un problema non previsto). Quindi usare qualcun altro sembra l'opzione migliore. – rectangletangle

risposta

14

Sembra che il modulo compiler dispone di un'implementazione di Python per questo, la firma è mangle(name, klass) dove klass è il nome della classe, non l'oggetto stesso.

Ecco come è possibile accedere e utilizzare:

>>> from compiler.misc import mangle 
>>> mangle('__some_such', 'Foo') 
'_Foo__some_such' 

Nota che il modulo compilatore è deprecato dal Python 2.6 e non esiste in Python 3.0.

Ecco la funzione stessa (da Python 2.7 source code) nel caso in cui si desidera solo per copiarlo nella vostra fonte o verificare che la versione è equivalente:

MANGLE_LEN = 256 # magic constant from compile.c 

def mangle(name, klass): 
    if not name.startswith('__'): 
     return name 
    if len(name) + 2 >= MANGLE_LEN: 
     return name 
    if name.endswith('__'): 
     return name 
    try: 
     i = 0 
     while klass[i] == '_': 
      i = i + 1 
    except IndexError: 
     return name 
    klass = klass[i:] 

    tlen = len(klass) + len(name) 
    if tlen > MANGLE_LEN: 
     klass = klass[:MANGLE_LEN-tlen] 

    return "_%s%s" % (klass, name) 
+0

Funziona, grazie! – rectangletangle

+1

Non c'è alcuna sostituzione di stdlib in Python 3? Mi sembra che sarebbe meglio per noi una funzione di libreria, nel caso qualcuno usasse un valore diverso da 256. Ad esempio, che cosa usano PyPy, Jython e IronPython? – asmeurer

Problemi correlati