2012-06-13 14 views
8

Czy w bibliotece standardowej Pythona znajduje się funkcja do odtworzenia schematu mieszania nazw Pythona z "prywatną" nazwą atrybutu? Wygląda na to, że będzie, ale nie mogę go znaleźć dla mojego życia.Funkcja wymazywania nazw w języku Python

Napisałem to, ale jeśli jest lepszy sposób, jestem uszy.

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

Jestem całkiem pewien, że nie ma takiej funkcji w standardowa biblioteka. Do czego ci to potrzebne? –

+8

Mogę sobie wyobrazić, że to prawie zawsze będzie używane do robienia czegoś złego. –

+0

Zasadniczo potrzebuję dynamicznego dostępu do prywatnych atrybutów dowolnej klasy. Powyższa funkcja działa; jednak mogą istnieć problemy, których nie jestem świadomy (niektóre nieprzewidziane problemy). Używanie kogoś innego wydaje się najlepszą opcją. – rectangletangle

Odpowiedz

14

To wygląda moduł compiler ma wdrożenie Pythona do tego, podpis jest mangle(name, klass) gdzie klass jest nazwa klasy, a nie sam obiekt.

Oto w jaki sposób można uzyskać dostęp i używać go:

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

Zauważ, że moduł kompilator jest nieaktualna od Pythona 2.6 i nie istnieje w Pythonie 3.0.

Oto sama (od Python 2.7 source code) funkcja w przypadku chcesz po prostu skopiować go do źródła lub sprawdzić, czy wersja jest równoważne:

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

To działa, dziękuję! – rectangletangle

+1

Czy w Pythonie 3 nie ma wymiany stdlib? Wydaje mi się, że byłoby lepiej dla nas funkcji bibliotecznej, na wypadek gdyby ktoś użył innej wartości niż 256. Na przykład, co używa PyPy, Jython i IronPython? – asmeurer

Powiązane problemy