【问题标题】:Private name mangling function私有名称修改功能
【发布时间】:2012-06-16 23:16:02
【问题描述】:

Python 标准库中是否有一个函数可以用“私有”属性名称重现 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)

【问题讨论】:

  • 我很确定标准库中没有这样的功能。你需要它做什么?
  • 我可以想象这几乎总是会被用来做坏事。
  • Lattyware 的预测得到证实。
  • 这就是为什么使用错误名称作为“私人”名称是一个的想法,恕我直言。如果您想将名称标记为私有以吓唬人们不要在外部使用它,只需使用一个下划线即可。名称修改不是为创建私有名称而设计的,它旨在在继承层次结构中的多个类可能想要使用相同名称时消除名称的歧义(因为 Python 的对象模型意味着继承层次结构中的所有类共享实例中相同的属性命名空间)。
  • 我写了一个装饰器,它在运行一个函数之前“断言”一个属性值。在这种情况下,能够让用户断言甚至是私有属性是很好的。我没有这样做,但让外部函数访问私有属性是一个正当的理由。这就是把我带到这里的原因:stackoverflow.com/questions/12537904/…

标签: python oop name-mangling


【解决方案1】:

看起来compiler 模块对此有一个Python 实现,签名是mangle(name, klass),其中klass 是类名,而不是对象本身。

您可以通过以下方式访问和使用它:

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

请注意,编译器模块自 Python 2.6 起已弃用,并且在 Python 3.0 中不存在。

这是函数本身(来自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)

【讨论】:

  • Python 3 中没有 stdlib 替代品吗?在我看来,如果有人使用与 256 不同的值,对我们来说最好使用库函数。例如,PyPy、Jython 和 IronPython 使用什么?
猜你喜欢
  • 2010-11-12
  • 1970-01-01
  • 2015-10-23
  • 1970-01-01
  • 1970-01-01
  • 2011-11-19
相关资源
最近更新 更多