Python 绑定需要访问私有变量的外部方法:Feature还是Bug?
SHORT VERSION:绑定到实例的外部方法无法通过Python 绑定需要访问私有变量的外部方法:Feature还是Bug?,python,cpython,Python,Cpython,SHORT VERSION:绑定到实例的外部方法无法通过self直接访问私有变量。这是一个特性还是一个bug 扩展版(带说明和示例): 在中,Alex Martelli解释了将函数绑定到实例的简单方法 使用此方法,可以使用外部函数设置类中的实例方法(在\uuu init\uu中) 但是,当绑定到实例的函数需要访问私有变量时,就会出现这种情况。这是因为名称损坏发生在\u Py\u Mangle中的步骤中,因此该函数从未有机会调用\uuuuu getattribute\uuuuu(“\u class
self直接访问私有变量。这是一个特性还是一个bug
扩展版(带说明和示例):
在中,Alex Martelli解释了将函数绑定到实例的简单方法
使用此方法,可以使用外部函数设置类中的实例方法(在\uuu init\uu
中)
但是,当绑定到实例的函数需要访问私有变量时,就会出现这种情况。这是因为名称损坏发生在\u Py\u Mangle
中的步骤中,因此该函数从未有机会调用\uuuuu getattribute\uuuuu(“\u classname\uu privatevarname”)
例如,如果我们定义一个简单的外部加法函数来访问私有实例变量\uuuuuobj\uval
:
def add_extern(self, value):
return self.__obj_val + value
并将其绑定到中的每个实例,同时在类定义中定义类似的实例方法add\u intern
class TestClass(object):
def __init__(self, object_value):
self.__obj_val = object_value
self.add_extern = add_extern.__get__(self, TestClass)
def add_intern(self, value):
return self.__obj_val + value
然后,内部方法将工作,但外部绑定方法将引发异常:
>>> t = TestClass(0)
>>> t.add_intern(1)
1
>>> t.add_extern(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in add_extern
AttributeError: 'TestClass' object has no attribute '__obj_val'
但是,这并没有将变量留给外部调用方,这是我们不希望的。由于Python的原因,存储在t
上的属性的实际名称是\u TestClass\u obj\u val
(如您在dir(t)
中所见)。没有在类上定义的外部函数只是查找\uuuuuj\uval
损坏的名称存储在函数的代码对象(例如,t.add\u extern.func\u code.co\u names
)中,并且是只读的,因此没有简单的更新方法
所以有理由不使用这种技术。。。至少是名字有问题。我100%知道这一切。我很好奇这是一个特性还是一个bug。将函数绑定到实例的操作在某些方面是不完整的绑定,因此在我看来这是一个bug。不过这真的是个小案子,所以没什么大不了的。是的,看起来像个bug,但我不认为创建新的实例方法是有文档记录的。很明显,mangling stuff的名称在函数构造函数中,而不是它所属的方法构造函数中。
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)