2012-06-13 4 views
8

Gibt es eine Funktion in der Python-Standardbibliothek, Python-Name Mangling-Schema mit einem "privaten" Attributnamen zu reproduzieren? Es scheint so als würde es sein, aber ich kann es nicht für mein Leben finden.Python-Name Mangling-Funktion

Ich schrieb dies, aber wenn es einen besseren Weg gibt, bin ich ganz Ohr.

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

Ich bin mir ziemlich sicher, dass es keine solche Funktion in der Standardbibliothek. Wofür brauchst du es? –

+8

Ich kann mir vorstellen, dass dies fast immer dazu verwendet wird, etwas Schlechtes zu tun. –

+0

Grundsätzlich muss ich dynamisch auf die privaten Attribute einer beliebigen Klasse zugreifen. Die obige Funktion funktioniert; Allerdings kann es Probleme geben, die mir unbekannt sind (einige unvorhergesehene Probleme). Es scheint also die beste Option zu sein, jemand anderes zu benutzen. – rectangletangle

Antwort

14

Es sieht aus wie das compiler Modul eine Python-Implementierung für diese hat, die Unterschrift ist mangle(name, klass) wo klass der Name der Klasse ist, nicht das Objekt selbst.

Hier ist, wie Sie zugreifen können und es verwenden:

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

Beachten Sie, dass der Compiler-Modul seit Python 2.6 ist veraltet und existiert nicht in Python 3.0. Hier

ist die Funktion selbst (von Python 2.7 source code), falls Sie es einfach in Ihre Quelle kopieren möchten oder überprüfen, ob Ihre Version entspricht:

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

Das funktioniert, danke! – rectangletangle

+1

Gibt es in Python 3 keinen Ersatz für stdlib? Es scheint mir, dass es besser wäre, eine Bibliotheksfunktion zu verwenden, falls jemand einen anderen Wert als 256 verwendet. Was zum Beispiel verwenden PyPy, Jython und IronPython? – asmeurer