doc: update docs/python.md (#408)

This commit is contained in:
砹小翼 2023-08-05 09:32:30 +08:00 committed by GitHub
parent 80b0443823
commit c06cbe37f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1392,6 +1392,187 @@ print(Yoki.legs) # => 4
Yoki.sound() # => Woof!
```
Python 数据模型
--------
更多请移步 <https://docs.python.org/zh-cn/3/reference/datamodel.html>
### 自定义类创建
参见 [自定义类创建](https://docs.python.org/zh-cn/3/reference/datamodel.html#customizing-class-creation) 。
```python
from typing import Any
class Object:
def __new__(cls, *args, **kwargs) -> "self":
# new 和 init 声明的参数必须一致
# 或者用 *args 和 **kwargs 进行兼容
return object.__new__(cls)
def __init__(self, *args, **kwargs):
# 初始化方法没有返回值,也不能返回值。
pass
def __call__(self, *args, **kwargs) -> Any:
pass
# 依次调用了 new 和 init所以如果
# 手动调用 new那么别忘了调用 init
obj = Object()
# 触发 __call__ 方法,要给什么参数取决于声明
obj()
```
### 上下文管理器
<!--rehype:wrap-class=col-span-2-->
参见 [上下文管理器](https://docs.python.org/zh-cn/3/reference/datamodel.html#with-statement-context-managers) 。
```python
from typing import Any
class Object:
def __enter__(self) -> Optional[Any]:
# with 语句会将返回值绑定到 as 子句中的变量,如果有的话。
return
def __exit__(self, exc_type, exc_value, traceback):
# 若 with 内没有发生异常,则三个参数都是 None 。
# 不应该重新引发传入的异常,这是调用者的责任。
pass
with Object() as alias:
# 进入 with 之前调用 obj.__enter__() 并得到 alias如果有返回的话
pass
# 离开 with 后调用 obj.__exit__() ,不管是正常结束还是因异常抛出而离开。
# 当需要获取 Object 的对象时可以这样写
obj = Object()
with obj as alias:
pass
```
### 特殊方法
<!--rehype:wrap-class=col-span-3-->
下表使用 `-> *` 代表返回值类型是任意的,或者需要视情况而定,实际上并不存在这种写法。
诸如 `-> str` 仅表示绝大多数情况下应当返回 `str` 类型,或者推荐返回 `str` 类型。
没有 `->` 的方法一般没有返回值。
参见 <https://docs.python.org/zh-cn/3/reference/datamodel.html>
| 语句 | 特殊方法 | 备注 | |
|---------------------|------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----|
| `repr(obj)` | `__repr__(self) -> str` | 详见 [`repr()`](https://docs.python.org/zh-cn/3/library/functions.html#repr) 。 | |
| `str(obj)` | `__str__(self) -> str` | 详见 [`str` 类型](https://docs.python.org/zh-cn/3/library/stdtypes.html#str) 。 | |
| `bytes(obj)` | `__bytes__(self) -> bytes` | 详见 [`bytes()`](https://docs.python.org/zh-cn/3/library/functions.html#func-bytes) 。 | |
| `format(obj, spec)` | `__format__(self, spec) -> str` | 详见 [`format()`](https://docs.python.org/zh-cn/3/library/functions.html#format)、[格式化字符串字面值](https://docs.python.org/zh-cn/3/reference/lexical_analysis.html#f-strings)、[格式规格迷你语言](https://docs.python.org/zh-cn/3/library/string.html#formatspec) 。 | |
| `hash(obj)` | `__hash__(self) -> int` | 详见 [`hash()`](https://docs.python.org/zh-cn/3/library/functions.html#hash) 。 | |
| `bool(obj)` | `__bool__(self) -> bool` | 未定义时调用 `obj.__len__() != 0` ,若 `__len__()` 也未定义,则所有对象都被视为 `True` 。另见 [`bool()`](https://docs.python.org/zh-cn/3/library/functions.html#bool) 。 | |
| `dir(obj)` | `__dir__(self) -> list` | 返回值必须是一个序列,[`dir()`](https://docs.python.org/zh-cn/3/library/functions.html#dir) 会把返回的序列转换为列表并对其排序。 | |
| `Object[key]` | `__class_getitem__(cls, key) -> *` | 不建议用于除了 [模拟泛型类型](https://docs.python.org/zh-cn/3/reference/datamodel.html#emulating-generic-types) 以外的用途,避免 IDE 误判。 | |
- 自定义实例及子类检查,参见 <https://docs.python.org/zh-cn/3/reference/datamodel.html#customizing-instance-and-subclass-checks>
| 语句 | 特殊方法 | 备注 | |
|-------------------------------|---------------------------------------------------|:------------------------------------------|-----|
| `isinstance(instance, class)` | `class.__instancecheck__(self, instance) -> bool` | 如果 instance 应被视为 class 的一个(直接或间接)实例则返回真值。 | |
| `issubclass(subclass, class)` | `class.__subclasscheck__(self, subclass) -> bool` | 如果 subclass 应被视为 class 的一个(直接或间接)子类则返回真值。 | |
- “富比较”方法,参见 <https://docs.python.org/zh-cn/3/reference/datamodel.html#object.__lt__>
| 语句 | 特殊方法 | 备注 | |
|-----------------|--------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------|-----|
| `obj < other` | `__lt__(self, other) -> bool` | | |
| `obj <= other` | `__le__(self, other) -> bool` | | |
| `obj == other` | `__eq__(self, other) -> bool` | 默认返回 `obj is other` ,如果结果为 `False` ,则会返回 [`NotImplemented`](https://docs.python.org/zh-cn/3/reference/datamodel.html#the-standard-type-hierarchy) 。 | |
| `obj != other` | `__ne__(self, other) -> bool` | 默认返回 `not obj.__eq__(other)` 。 | |
| `obj > other` | `__gt__(self, other) -> bool` | | |
| `obj >= other` | `__ge__(self, other) -> bool` | | |
- 自定义属性访问,参见 <https://docs.python.org/zh-cn/3/reference/datamodel.html#customizing-attribute-access>
| 语句 | 特殊方法 | 备注 | |
|---------------------|-------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------|-----|
| `obj.name` | `__getattr__(self, name) -> *` | 优先调用。当抛出 [`AttributeError`](https://docs.python.org/zh-cn/3/library/exceptions.html#AttributeError) 时转向调用 `__getattribute__()` 。 | |
| `obj.name` | `__getattribute__(self, name) -> *` | 参见 [自定义属性访问](https://docs.python.org/zh-cn/3/reference/datamodel.html#customizing-attribute-access) 避免无限递归。 | |
| `obj.name = value` | `__setattr__(self, name, value)` | | |
| `del obj.name` | `__delattr__(self, name)` | 仅在 `del obj.name` 对于该对象有意义时才应该被实现。 | |
- 模拟容器类型,参见 <https://docs.python.org/zh-cn/3/reference/datamodel.html#emulating-container-types>
| 语句 | 特殊方法 | 备注 | |
|-----------------------|------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----|
| `len(obj)` | `__len__(self) -> int` | | |
| `op.length_hint(obj)` | `__length_hint__(self) -> int` | 在使用标准库 [operator](https://docs.python.org/zh-cn/3/library/operator.html) 的 [`length_hint()`](https://docs.python.org/zh-cn/3/library/operator.html#operator.length_hint) 时会被调用Python 3.4+)。 | |
| `obj[key]` | `__getitem__(self, key) -> *` | 需要抛出 [IndexError](https://docs.python.org/zh-cn/3/library/exceptions.html#IndexError) 以便正确地结束 [for](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#for) 循环。 | |
| `obj[key]` | `__missing__(self, key) -> *` | 仅在 dict 的子类找不到键时被调用(不能重写 `__getitem__` 方法)。 | |
| `obj[key] = value` | `__setitem__(self, key, value)` | `a[1:2] = b` 实际上是 `a[slice(1, 2, None)] = b` ,其它情形及在其余方法中同理。详见 [`slice()`](https://docs.python.org/zh-cn/3/library/functions.html#slice) 。 | |
| `del obj[key]` | `__delitem__(self, key)` | | |
| _调用途径有很多_ | `__iter__(self) -> Iterator` | 在需要创建一个 [迭代器](https://docs.python.org/zh-cn/3/glossary.html#term-iterator) 时被调用,例如使用 [`iter()`](https://docs.python.org/zh-cn/3/library/functions.html#iter) 、 [`for` 循环](https://docs.python.org/zh-cn/3/reference/compound_stmts.html#for) 。<br>最好返回一个新对象,因为迭代器在语义上是一次性的。若返回 `self` ,则必须实现 `__next__()` 方法。 | |
| `reversed(obj)` | `__reversed__(self) -> *` | 详见 [`reversed()`](https://docs.python.org/zh-cn/3/library/functions.html#reversed) 。 | |
| `item in obj` | `__contains__(self, item) -> bool` | 对于未定义该方法的对象在 `in``not in` 时,参考 [成员检测运算](https://docs.python.org/zh-cn/3/reference/expressions.html#membership-test-details) 。 | |
- 模拟数字类型,参见 <https://docs.python.org/zh-cn/3/reference/datamodel.html#emulating-numeric-types>
| 语句 | 特殊方法 | 备注 | |
|----------------------|------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----|
| `+obj` | `__neg__(self) -> *` | | |
| `-obj` | `__pos__(self) -> *` | | |
| `~obj` | `__invert__(self) -> *` | | |
| `abs(obj)` | `__abs__(self) -> *` | | |
| `int(obj)` | `__int__(self) -> *` | | |
| `float(obj)` | `__float__(self) -> *` | | |
| `complex(obj)` | `__complex__(self) -> *` | | |
| `round(obj)` | `__round__(self) -> int` | 详见 [`round()`](https://docs.python.org/zh-cn/3/library/functions.html#round) 。 | |
| `round(obj)` | `__round__(self, ndigits) -> *` | 详见 [`round()`](https://docs.python.org/zh-cn/3/library/functions.html#round) 。 | |
| `math.ceil(obj)` | `__ceil__(self) -> int` | 详见标准库 [math](https://docs.python.org/zh-cn/3/library/math.html#module-math) 的 [`ceil()`](https://docs.python.org/zh-cn/3/library/math.html#math.ceil) 。 | |
| `math.floor(obj)` | `__floor__(self) -> int` | 详见标准库 [math](https://docs.python.org/zh-cn/3/library/math.html#module-math) 的 [`floor()`](https://docs.python.org/zh-cn/3/library/math.html#math.floor) 。 | |
| `math.trunc(obj)` | `__trunc__(self) -> int` | 详见标准库 [math](https://docs.python.org/zh-cn/3/library/math.html#module-math) 的 [`trunc()`](https://docs.python.org/zh-cn/3/library/math.html#math.trunc) 。 | |
| | `__index__(self) -> int` | 需要无损地将数值转换为整数的时候会被调用。详见 [这里](https://docs.python.org/zh-cn/3/reference/datamodel.html#object.__index__) 。 | |
| `obj + other` | `__add__(self, other) -> *` | | |
| `obj - other` | `__sub__(self, other) -> *` | | |
| `obj * other` | `__mul__(self, other) -> *` | | |
| `obj @ other` | `__matmul__(self, other) -> *` | 为第三方库而生的矩阵乘法运算符,[这里](https://docs.python.org/zh-cn/3/reference/expressions.html#binary-arithmetic-operations)提了一嘴。Python 3.5+ | |
| `obj / other` | `__truediv__(self, other) -> *` | | |
| `obj // other` | `__floordiv__(self, other) -> *` | | |
| `obj % other` | `__mod__(self, other) -> *` | | |
| `divmod(obj, other)` | `__divmod__(self, other) -> tuple` | `divmod(a, b)` 返回一个元组 `(a // b, a % b)` ,详见 [`divmod()`](https://docs.python.org/zh-cn/3/library/functions.html#divmod) 。 | |
| `obj ** exp` | `__pow__(self, exp) -> *` | | |
| `pow(obj, exp, mod)` | `__pow__(self, exp, mod) -> *` | `pow(base, exp, mod)``pow(base, exp) % mod` 更高效。 | |
| `obj << other` | `__lshift__(self, other) -> *` | | |
| `obj >> other` | `__rshift__(self, other) -> *` | | |
| `obj & other` | `__and__(self, other) -> *` | | |
| `obj ^ other` | `__xor__(self, other) -> *` | | |
| `obj \| other` | `__or__(self, other) -> *` | | |
| `other + obj` | `__radd__(self, obj) -> *` | 仅当 obj 未定义 `__add__()` 或其返回 `NotImplemented` <br>且与 other 互相都没有继承关系时,调用 other 的 `__radd__()` 。详见 [这里](https://docs.python.org/zh-cn/3/reference/datamodel.html#object.__radd__) 。 | |
| `other - obj` | `__rsub__(self, obj) -> *` | 以下,如此类推。 | |
| `other * obj` | `__rmul__(self, obj) -> *` | | |
| `other @ obj` | `__rmatmul__(self, obj) -> *` | | |
| `other / obj` | `__rtruediv__(self, obj) -> *` | | |
| `other // obj` | `__rfloordiv__(self, obj) -> *` | | |
| `other % obj` | `__rmod__(self, obj) -> *` | | |
| `divmod(other, obj)` | `__rdivmod__(self, obj) -> tuple` | | |
| `other ** obj` | `__rpow__(self, obj) -> *` | | |
| | `__rpow__(self, obj, mod) -> *` | `pow(obj, other, mod)` 不会尝试调用 `other.__rpow__(obj, mod)` ,因为强制转换规则会太过复杂。 | |
| `other << obj` | `__rlshift__(self, obj) -> *` | | |
| `other >> obj` | `__rrshift__(self, obj) -> *` | | |
| `other & obj` | `__rand__(self, obj) -> *` | | |
| `other ^ obj` | `__rxor__(self, obj) -> *` | | |
| `other \| obj` | `__ror__(self, obj) -> *` | | |
| `obj += other` | `__iadd__(self, other) -> *` | 若方法已定义,则 `a += b` 等价于 `a.__iadd(b)` <br>若未定义,则回退到 `a + b` 选择 `x.__add__(y)``y.__radd__(x)` 。 | |
| `obj -= other` | `__isub__(self, other) -> *` | 以下,如此类推。 | |
| `obj *= other` | `__imul__(self, other) -> *` | | |
| `obj @= other` | `__imatmul__(self, other) -> *` | | |
| `obj /= other` | `__itruediv__(self, other) -> *` | | |
| `obj //= other` | `__ifloordiv__(self, other) -> *` | | |
| `obj %= other` | `__imod__(self, other) -> *` | | |
| `obj **= exp` | `__ipow__(self, other) -> *` | | |
| `obj <<= other` | `__ilshift__(self, other) -> *` | | |
| `obj >>= other` | `__irshift__(self, other) -> *` | | |
| `obj &= other` | `__iand__(self, other) -> *` | | |
| `obj ^= other` | `__ixor__(self, other) -> *` | | |
| `obj \|= other` | `__ior__(self, other) -> *` | | |
Python 类型标注 (Python 3.5+)
--------