Class可以定义对象。
对象发消息实际上就是调用对象对应的关联函数，我们称之为对象的方法。
同一个函数总是处理同一类结构的数据，或者多个函数共享同一个状态变量时，就该把代码重构为 `class` 。一个Class内的一个实例为instance
判断一个变量是否是某个类型可以用`isinstance()`判断：
```plain
>>> isinstance(a, list)
True
>>> isinstance(b, Animal)
True
```
例如：
````python
class Student(object):
    def __init__(self, name, score): #定义类的内容
        self.__name = name
        self.__score = score

    def print_score(self): #数据封装，使得类可以直接输出instance
        print('%s: %s' % (self.__name, self.__score)) #__表示private variable，如果是一个_var则可以从外部修改但尽量不要
        
    def set_score(self, score): ##定义一个这样的函数后可以检查输入
        if 0 <= score <= 100:
            self.__score = score
        else:
            raise ValueError('bad score')
````
类具有继承和多态的性质。

高级的面向对象变成有
@property -> 让属性访问触发方法
_Slot_ 限制外部编辑
多重继承 ->class Dog(Mammal, Runnable):

定制类，用到的时候再搜：

1. 字符串与显示

- `__str__`：定义使用 `print()` 或 `str()` 时的**可读输出**。
- `__repr__`：定义交互式环境中直接输出对象时的**开发者模式输出**。

2. 迭代与容器

- `__iter__` 及 `__next__`：让类支持 `for...in` 循环，成为**可迭代对象**。
- `__getitem__`：允许通过**下标或切片**（如 `obj[key]`）访问元素。
- `__setitem__`：允许通过下标**修改**元素。
- `__len__`：让类支持内建函数 `len()`。 [

3. 属性动态访问

- `__getattr__`：当尝试访问**不存在**的属性时触发。
- `__setattr__`：拦截属性赋值操作，常用于实现属性校验。
1. 运行与调用

- `__call__`：将对象变为**可调用对象**，允许像调用函数一样直接使用实例（如 `obj()`）。

5. 高级定制

- `__slots__`：限制类动态添加属性，**节省内存空间**。
- `__enter__` 及 `__exit__`：定义上下文管理器，支持 `with` 语句，自动处理资源分配与释放。
- `__add__`：定义对象使用 `+` 运算符时的相加逻辑。

枚举类？
元类？type()创建动态class， metaclass
```python
# metaclass是类的模板，所以必须从`type`类型派生：
class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)
```
这两个感觉用不到
