短版本:绑定到实例的外部方法不能通过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
但外部方法将引发一个外部方法的工作:
^{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)
但是,这并没有将变量私有化给外部调用者,这是我们不想要的。在
由于Python的name-mangling,存储在
t
上的属性的实际名称是_TestClass__obj_val
(如dir(t)
中所示)。外部函数没有在类上定义,它只是寻找__obj_val
。在损坏的名称存储在函数的code对象中(例如
t.add_extern.func_code.co_names
),并且是只读的,因此没有简单的方法来更新它。在有理由不使用这个技巧。。。至少名字有点混乱。在
相关问题 更多 >
编程相关推荐