class Enrollment(object):
def __init__(self,enrollmentId=None, enrollmentReference=None):
self.enrollmentId = enrollmentId
self.enrollmentReference = enrollmentReference
@property
def enrollmentId(self):
return self.__enrollmentId
@enrollmentId.setter
def enrollmentId(self, enrollmentId):
self.__enrollmentId = enrollmentId
@property
def enrollmentReference(self):
return self.__enrollmentReference
@enrollmentReference.setter
def enrollmentReference(self, enrollmentReference):
self.__enrollmentReference = enrollmentReference
如果我现在尝试打印上述类的属性:
print(Enrollment().__dict__)
它打印前缀为类名的属性,如下所示:
{'_Enrollment__enrollmentId': None, '_Enrollment__enrollmentReference': None}
注意:如果我将对象删除为超类,则一切正常并且正确打印属性,如下所示:
{'enrollmentId': None, 'enrollmentReference': None}
我一直在我身边缠绕了2天,没有运气。
无法理解为什么类名称以属性为前缀。我需要将Enrollment
对象序列化为JSON。
答案 0 :(得分:1)
在类定义中,Python将__x
转换为_classname__x
。这称为name mangling。它的目的是支持类本地引用,以便子类不会无意中破坏父类的内部逻辑。
答案 1 :(得分:0)
这是因为Python的name mangling类属性名称以__
开头,后缀最多只有一个_
。这表明这些属性的隐私更加严格。
注意:这仍然是一种启发式方法,不应该被用于访问预防。
来自文档:
__spam形式的任何标识符(至少两个前导下划线,最多一个尾随下划线)在文本上用_classname__spam替换,其中classname是当前的类名,其中前导下划线被剥离。
class A:
def __foo_(self): pass
print(vars(A))
输出
{'__module__': '__main__', '_A__foo_': <function A.__foo_ at 0x1118c2488>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
请注意,__foo_
已被误导为_A__foo_
。
为什么这会有用?那么来自文档的例子非常引人注目:
名称修改有助于让子类覆盖方法而不破坏类内方法调用。例如:
class Mapping:
def __init__(self, iterable):
self.items_list = []
self.__update(iterable)
def update(self, iterable):
for item in iterable:
self.items_list.append(item)
__update = update # private copy of original update() method
class MappingSubclass(Mapping):
def update(self, keys, values):
# provides new signature for update()
# but does not break __init__()
for item in zip(keys, values):
self.items_list.append(item)