# 类的访问控制

## 1、类属性的访问控制

在 Java 中，有 public （公共）属性 和 private （私有）属性，这可以对属性进行访问控制。

那么在 Python 中有没有属性的访问控制呢？

一般情况下，我们会使用 `__private_attrs` 两个下划线开头，声明该属性为私有，不能在类地外部被使用或直接访问。在类内部的方法中使用时 `self.__private_attrs`。

为什么只能说一般情况下呢？

因为实际上， Python 中是没有提供私有属性等功能的。

但是 Python 对属性的访问控制是靠程序员自觉的。为什么这么说呢？

看看下面的示例：

![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-Python%20%E5%B1%9E%E6%80%A7%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6.png)

仔细看图片，为什么说双下划线不是真正的私有属性呢？我们看下下面的例子，用下面的例子来验证：

```python

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

class UserInfo(object):
    def __init__(self, name, age, account):
        self.name = name
        self._age = age
        self.__account = account

    def get_account(self):
        return self.__account


if __name__ == '__main__':
    userInfo = UserInfo('两点水', 23, 347073565);
    # 打印所有属性
    print(dir(userInfo))
    # 打印构造函数中的属性
    print(userInfo.__dict__)
    print(userInfo.get_account())
    # 用于验证双下划线是否是真正的私有属性
    print(userInfo._UserInfo__account)


```

输出的结果如下图：

![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-Python%E5%8F%8C%E4%B8%8B%E5%88%92%E7%BA%BF%E5%B1%9E%E6%80%A7.png)

## 2、类专有的方法

一个类创建的时候，就会包含一些方法，主要有以下方法：

类的专有方法：

| 方法            | 说明            |
| ------------- | ------------- |
| `__init__`    | 构造函数，在生成对象时调用 |
| `__del__`     | 析构函数，释放对象时使用  |
| `__repr__`    | 打印，转换         |
| `__setitem__` | 按照索引赋值        |
| `__getitem__` | 按照索引获取值       |
| `__len__`     | 获得长度          |
| `__cmp__`     | 比较运算          |
| `__call__`    | 函数调用          |
| `__add__`     | 加运算           |
| `__sub__`     | 减运算           |
| `__mul__`     | 乘运算           |
| `__div__`     | 除运算           |
| `__mod__`     | 求余运算          |
| `__pow__`     | 乘方            |

当然有些时候我们需要获取类的相关信息，我们可以使用如下的方法：

* `type(obj)`：来获取对象的相应类型；
* `isinstance(obj, type)`：判断对象是否为指定的 type 类型的实例；
* `hasattr(obj, attr)`：判断对象是否具有指定属性/方法；
* `getattr(obj, attr[, default])` 获取属性/方法的值, 要是没有对应的属性则返回 default 值（前提是设置了 default），否则会抛出 AttributeError 异常；
* `setattr(obj, attr, value)`：设定该属性/方法的值，类似于 obj.attr=value；
* `dir(obj)`：可以获取相应对象的所有属性和方法名的列表：

## 3、方法的访问控制

其实我们也可以把方法看成是类的属性的，那么方法的访问控制也是跟属性是一样的，也是没有实质上的私有方法。一切都是靠程序员自觉遵守 Python 的编程规范。

示例如下，具体规则也是跟属性一样的，

```python
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

class User(object):
    def upgrade(self):
        pass

    def _buy_equipment(self):
        pass

    def __pk(self):
        pass

```
