2012-06-13 12 views
8

¿Hay una función en la biblioteca estándar de Python para reproducir el esquema de creación de nombres de Python con un nombre de atributo "privado"? Parece que habría, pero no puedo encontrarlo por mi vida.Función de creación de nombres de Python

Escribí esto, pero si hay una mejor manera en que soy todo oídos.

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

Estoy bastante seguro de que no hay tal función en el biblioteca estándar. ¿Para qué lo necesitas? –

+8

Me imagino que esto casi siempre va a usarse para hacer algo malo. –

+0

Básicamente, necesito acceder dinámicamente a los atributos privados de una clase arbitraria. La función anterior funciona; sin embargo, puede haber problemas que desconozco (algún problema imprevisto). Entonces, usar la de otra persona parece ser la mejor opción. – rectangletangle

Respuesta

14

Parece que el módulo compiler tiene una implementación de Python para esto, la firma es mangle(name, klass) donde klass es el nombre de la clase, no el objeto en sí.

Aquí es cómo puede acceder y utilizarla:

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

Tenga en cuenta que el módulo compilador está obsoleta desde Python 2.6 y no existe en Python 3.0.

Aquí es la propia función (de Python 2.7 source code) en caso de que lo que desea es copiarlo en su fuente o verificar que su versión es 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

Esto funciona, ¡gracias! – rectangletangle

+1

¿No hay reemplazo stdlib en Python 3? Me parece que sería mejor para nosotros una función de biblioteca, en caso de que alguien use un valor diferente a 256. Por ejemplo, ¿qué usan PyPy, Jython e IronPython? – asmeurer

Cuestiones relacionadas