使用绑定外部方法访问私有变量:特性还是错误?

2024-05-12 22:53:09 发布

您现在位置:Python中文网/ 问答频道 /正文

短版本:绑定到实例的外部方法不能通过self.__privatevarname直接访问私有变量。这是一个特性还是一个bug?在

扩展版(带说明和示例)

Python: Bind an Unbound Method?中,Alex Martelli解释了一个将函数绑定到实例的简单方法。在

使用此方法,可以使用外部函数来设置类(在__init__)中的实例方法。在

但是,当绑定到实例的函数需要访问私有变量时,这种情况就会崩溃。这是因为名称损坏发生在_Py_Mangle中的compile步骤中,因此函数永远没有机会调用__getattribute__('_classname__privatevarname')。在

例如,如果我们定义一个简单的外部加法函数来访问私有实例变量__obj_val

def add_extern(self, value):
  return self.__obj_val + value

并将其绑定到__init__中的每个实例,同时还在类定义中定义一个类似的实例方法add_intern

^{pr2}$

但外部方法将引发一个外部方法的工作:

^{3}$

POSTSCRIPT:您可以通过重写__getattribute__来为您进行损坏来克服此缺点:

class TestClass(object):
  ...
  def __getattribute__(self, name):
    try:
      return super(TestClass, self).__getattribute__(name)
    except AttributeError:
      # mimic behavior of _Py_Mangle
      if not name.startswith('__'):  # only private attrs
        raise
      if name.endswith('__'):  # don't mangle dunder attrs
        raise
      if '.' in name:  # don't mangle for modules
        raise
      if not name.lstrip('_'):  # don't mangle if just underscores
        raise

      mangled_name = '_{cls_name}{attr_name}'.format(
          cls_name=self.__class__.__name__, attr_name=name)
      return super(TestClass, self).__getattribute__(mangled_name)

但是,这并没有将变量私有化给外部调用者,这是我们不想要的。在


Tags: 实例方法函数nameselfreturnif定义
1条回答
网友
1楼 · 发布于 2024-05-12 22:53:09

由于Python的name-mangling,存储在t上的属性的实际名称是_TestClass__obj_val(如dir(t)中所示)。外部函数没有在类上定义,它只是寻找__obj_val。在

损坏的名称存储在函数的code对象中(例如t.add_extern.func_code.co_names),并且是只读的,因此没有简单的方法来更新它。在

有理由不使用这个技巧。。。至少名字有点混乱。在

相关问题 更多 >