内置 __dict__ 正在返回以 class 名称作为前缀的属性名称
built in __dict__ is returning names of attributes with class names as prefix
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
如果我现在尝试打印上面的属性 class:
print(Enrollment().__dict__)
它打印以 class 名称为前缀的属性,如下所示:
{'_Enrollment__enrollmentId': None, '_Enrollment__enrollmentReference': None}
注意:如果我将对象作为超级 class 删除,一切正常,它会正确打印属性,如下所示:
{'enrollmentId': None, 'enrollmentReference': None}
我已经为此苦苦思索了 2 天,但一直没有成功。
无法理解为什么 class 名称是属性的前缀。我需要将 Enrollment
对象序列化为 JSON.
在 class 定义中,Python 将 __x
转换为 _classname__x
。这叫做name mangling。它的目的是支持 class 本地引用,这样子 class 就不会无意中破坏父 class.
的内部逻辑
原因
这是由于 Python 的 name mangling 个 class 属性名称以 __
开头并且最多以一个 _
作为后缀.这表明对这些属性有更严格的隐私保护。
注意:这仍然是一种启发式方法,不应指望用于防止访问。
来自文档:
Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped.
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_
。
使用
为什么这可能有用?那么文档中的示例非常引人注目:
Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls. For example:
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)
tldr
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
如果我现在尝试打印上面的属性 class:
print(Enrollment().__dict__)
它打印以 class 名称为前缀的属性,如下所示:
{'_Enrollment__enrollmentId': None, '_Enrollment__enrollmentReference': None}
注意:如果我将对象作为超级 class 删除,一切正常,它会正确打印属性,如下所示:
{'enrollmentId': None, 'enrollmentReference': None}
我已经为此苦苦思索了 2 天,但一直没有成功。
无法理解为什么 class 名称是属性的前缀。我需要将 Enrollment
对象序列化为 JSON.
在 class 定义中,Python 将 __x
转换为 _classname__x
。这叫做name mangling。它的目的是支持 class 本地引用,这样子 class 就不会无意中破坏父 class.
原因
这是由于 Python 的 name mangling 个 class 属性名称以 __
开头并且最多以一个 _
作为后缀.这表明对这些属性有更严格的隐私保护。
注意:这仍然是一种启发式方法,不应指望用于防止访问。
来自文档:
Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped.
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_
。
使用
为什么这可能有用?那么文档中的示例非常引人注目:
Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls. For example:
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)