2012-06-13 20 views
8

Có hàm nào trong thư viện chuẩn Python để tạo lại lược đồ mang tên mang tên Python với tên thuộc tính "riêng tư" không? Nó có vẻ như sẽ có, nhưng tôi không thể tìm thấy nó cho cuộc sống của tôi.Hàm mangling tên Python

Tôi đã viết điều này, nhưng nếu có cách nào tốt hơn, tôi là tất cả các tai.

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

Tôi chắc chắn rằng không có chức năng như vậy trong thư viện chuẩn. Mày cần nó để làm gì? –

+8

Tôi có thể tưởng tượng điều này hầu như luôn luôn được sử dụng để làm điều gì đó xấu. –

+0

Về cơ bản, tôi cần truy cập động các thuộc tính riêng của lớp tùy ý. Hàm trên hoạt động; Tuy nhiên, có thể có vấn đề với nó mà tôi không biết (một số vấn đề không lường trước được). Vì vậy, sử dụng của người khác có vẻ như là lựa chọn tốt nhất. – rectangletangle

Trả lời

14

Dường như các mô-đun compiler có thực hiện Python cho điều này, chữ ký là mangle(name, klass) nơi klass là tên lớp, không phải là đối tượng của chính nó.

Đây là cách bạn có thể truy cập và sử dụng nó:

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

Lưu ý rằng các mô-đun trình biên dịch bị phản đối từ Python 2.6 và không tồn tại trong Python 3.0.

Dưới đây là chức năng riêng của mình (từ Python 2.7 source code) trong trường hợp bạn chỉ muốn sao chép nó vào mã nguồn của bạn hoặc xác minh rằng phiên bản của bạn là tương đương:

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

Công trình này, cảm ơn! – rectangletangle

+1

Không có sự thay thế stdlib nào trong Python 3? Dường như với tôi rằng nó sẽ là tốt hơn cho chúng tôi một chức năng thư viện, trong trường hợp ai đó sử dụng một giá trị khác nhau hơn 256. Ví dụ, những gì làm PyPy, Jython, và IronPython sử dụng? – asmeurer