blog/docs/code/python/private-variable.md

57 lines
2.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 私有变量
date: 2020-10-03 15:32:55
tags: [Python]
categories: [Python]
author: Anges黎梦
---
### 私有变量
那种仅限从一个对象内部访问的“私有”实例变量在 Python 中并不存在。
但是,大多数 Python 代码都遵循这样一个约定:带有一个下划线的名称 (例如 _spam) 应该被当作是 API 的非公有部分 (无论它是函数、方法或是数据成员)。
这应当被视为一个实现细节,可能不经通知即加以改变。
由于存在对于类私有成员的有效使用场景(例如避免名称与子类所定义的名称相冲突),因此存在对此种机制的有限支持,称为 名称改写。
任何形式为 __spam 的标识符(至少带有两个前缀下划线,至多一个后缀下划线)的文本将被替换为 _classname__spam其中 classname 为去除了前缀下划线的当前类名称。
这种改写不考虑标识符的句法位置,只要它出现在类定义内部就会进行。
名称改写有助于让子类重载方法而不破坏类内方法调用。例如:
```python
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)
```
上面的示例即使在 MappingSubclass 引入了一个 __update 标识符的情况下也不会出错,因为它会在 Mapping 类中被替换为 _Mapping__update 而在 MappingSubclass 类中被替换为 _MappingSubclass__update。
请注意,改写规则的设计主要是为了避免意外冲突;
访问或修改被视为私有的变量仍然是可能的。这在特殊情况下甚至会很有用,例如在调试器中。
请注意传递给 exec() 或 eval() 的代码不会将发起调用类的类名视作当前类;
这类似于 global 语句的效果,因此这种效果仅限于同时经过字节码编译的代码。
同样的限制也适用于 getattr(), setattr() 和 delattr(),以及对于 __dict__ 的直接引用。