2012-06-13 2 views
8

Pythonの標準ライブラリに、 "private"属性名を持つPythonの名前マングリングスキームを再現する関数はありますか?それがあるように見えるが、私は私の人生のためにそれを見つけることができない。Pythonネームマングリング関数

私はこれを書いていますが、もっと良い方法があれば私はすべて耳にします。 compilerモジュールは、このためのPython実装を持っているよう

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

私はそのような機能はありませんかなり確信しています標準ライブラリ。何のためにそれが必要ですか? –

+8

これはほとんどいつも悪いことをするのに使われるだろうと思う。 –

+0

基本的には、任意のクラスのプライベート属性に動的にアクセスする必要があります。上記の関数は機能します。しかし、私が気付いていない(予期せぬ問題がある)問題があるかもしれません。だから誰かを使うことが最善の選択肢のようだ。 – rectangletangle

答えて

14

に見え、署名はklassは、クラス名ではなく、オブジェクト自体であるmangle(name, klass)です。コンパイラモジュールは、Python 2.6以降廃止されており、Python 3.0で存在しないことを

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

注:ここでは

は、あなたがアクセスし、それを使用することができる方法です。あなたは自分のソースにコピーしたり、バージョンが同等であることを確認したい場合にはここで

は(Python 2.7 source codeから)関数自体です:

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

これは、ありがとう! – rectangletangle

+1

Python 3にはstdlibの置き換えはありませんか?誰かが256よりも異なる値を使用する場合は、ライブラリ関数を使う方が良いと思います。たとえば、PyPy、Jython、IronPythonは何を使用していますか? – asmeurer