doc: 阅读python文档
This commit is contained in:
120
python/py.md
120
python/py.md
@@ -94,6 +94,15 @@
|
|||||||
- [packages](#packages)
|
- [packages](#packages)
|
||||||
- [import \* from package](#import--from-package)
|
- [import \* from package](#import--from-package)
|
||||||
- [包内部相互引用](#包内部相互引用)
|
- [包内部相互引用](#包内部相互引用)
|
||||||
|
- [class](#class)
|
||||||
|
- [python scope and namespaces](#python-scope-and-namespaces)
|
||||||
|
- [namespace](#namespace)
|
||||||
|
- [lifetime](#lifetime)
|
||||||
|
- [LGEB](#lgeb)
|
||||||
|
- [scope](#scope)
|
||||||
|
- [global](#global)
|
||||||
|
- [nonlocal](#nonlocal)
|
||||||
|
- [global namespace](#global-namespace)
|
||||||
|
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
@@ -1055,6 +1064,8 @@ except* OSError as e:
|
|||||||
except* SystemError as e:
|
except* SystemError as e:
|
||||||
print("There were SystemErrors")
|
print("There were SystemErrors")
|
||||||
```
|
```
|
||||||
|
当使用`except*`语法时,即使指定了`except* OSError as e`,`e`的类型仍然是`ExceptionGroup`而不是`OSError`,因为try中抛出的`ConditionGroup`中可能含有多个`OSError`类型的异常,故而,实际的`OSError`异常对象需要通过`e.exceptions`来进行访问。
|
||||||
|
|
||||||
### enriching exceptions with notes
|
### enriching exceptions with notes
|
||||||
当创建异常时,可以通过`add_note(note)`方法来为异常补充信息,标准的traceback会按照其被添加的顺序渲染所有的note信息,note信息在异常信息之后
|
当创建异常时,可以通过`add_note(note)`方法来为异常补充信息,标准的traceback会按照其被添加的顺序渲染所有的note信息,note信息在异常信息之后
|
||||||
```py
|
```py
|
||||||
@@ -1570,4 +1581,113 @@ from .. import formats # 访问../formats
|
|||||||
from ..filters import equalizer # 访问../filters中的equalizer
|
from ..filters import equalizer # 访问../filters中的equalizer
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## class
|
||||||
|
python在对对象进行传递时,只支持引用传递(传递指向对象的指针),而不支持类似c++的值传递(对象拷贝)。故而,在python中,如果对方法的入参对象进行了修改,那么该修改对调用方可见。
|
||||||
|
|
||||||
|
### python scope and namespaces
|
||||||
|
#### namespace
|
||||||
|
namespace代表name到object的映射。
|
||||||
|
|
||||||
|
常见的namespace有:
|
||||||
|
- 包含built-in names的namespace(built-in names包含类似`abs`之类的built-in函数,以及built-in exception names等)
|
||||||
|
- 包含module global names的module namespace
|
||||||
|
- 在函数调用时包含`local names`的local namespace
|
||||||
|
|
||||||
|
从某种意义上说,对象中的attributes也构成了一个namespace。
|
||||||
|
|
||||||
|
对于`module.name`的访问,其实际也是针对`module object`中`attribute`的访问:module中的global name和module attribute都是位于同一namespace中。
|
||||||
|
|
||||||
|
`attribute`分为`read-only`和`writable`的。对于`writable`的attribute,可以对其进行赋值,示例如下:
|
||||||
|
```py
|
||||||
|
modname.the_answer = 42
|
||||||
|
```
|
||||||
|
同样的,`writable`的attribute也可以通过`del`来进行删除,删除后该attribute将会从对象中被移除
|
||||||
|
```py
|
||||||
|
del modname.the_answer
|
||||||
|
```
|
||||||
|
|
||||||
|
##### lifetime
|
||||||
|
在不同时机创建的namespace拥有不同的生命周期:
|
||||||
|
- `built-in namespace`: 在python interpreter启动时被创建,并且该namespace永远不会被删除
|
||||||
|
- `module namespace`: 当module的定义被读入时,会创建module namespace,并且module namespace会持续到interpreter退出时
|
||||||
|
- 对于被interpreter执行的top-level statements(通过交互式输入或从script中读取),其被视作`__main__`module的一部分,其拥有属于自己的namespace
|
||||||
|
- `local namespace of function`:在函数被调用时创建,在函数执行完成/抛出未处理异常时namespace被删除(对于递归调用,每次调用都拥有其自己的namespace)
|
||||||
|
|
||||||
|
##### LGEB
|
||||||
|
在python中,LEGB规则决定了命名空间搜索的顺序:
|
||||||
|
- `local`: 定义在函数/类内部
|
||||||
|
- `enclosed`:定义在闭包函数内
|
||||||
|
- `global`:定义在全局/最上层
|
||||||
|
- `built-in`:python中内置的保留名称
|
||||||
|
|
||||||
|
<img src="https://picx.zhimg.com/v2-9e322a731ae838a75dd2de84dae659e7_1440w.jpg" data-size="small" data-rawwidth="300" data-rawheight="260" data-original-token="v2-00f7cd30194a00ffd46c4fd5612b82c2" class="content_image" width="300">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##### scope
|
||||||
|
scope代表python程序中的一个文本范围,在该范围内可以对某个namespace中的name进行直接访问,而无需前缀`x.y.`之类的限定名。
|
||||||
|
|
||||||
|
在程序执行的某个时间点,都会存在3/4个nested scopes可以直接访问:
|
||||||
|
- 最内层的scope,包含local names,最先查找
|
||||||
|
- scope of enclosing function,查找时会从nearest neclosing scope开始,包含`non-local and non-global names`
|
||||||
|
- `next-to-last scope`,包含global names
|
||||||
|
- 最外层scope,最后查找,包含built-in names
|
||||||
|
|
||||||
|
##### global
|
||||||
|
如果使用`global var_name`的方式来声明变量,那么针对该变量的引用和复制都会直接指向global namespace中的变量。
|
||||||
|
|
||||||
|
##### nonlocal
|
||||||
|
如果想要在local namespace中访问enclosing namespace中的name,可以通过`nonlocal var_name`形式来声明变量,示例如下:
|
||||||
|
```py
|
||||||
|
def main():
|
||||||
|
s = "fuck"
|
||||||
|
def s_change(p):
|
||||||
|
nonlocal s
|
||||||
|
s=p
|
||||||
|
s_change("shit")
|
||||||
|
print(s)
|
||||||
|
```
|
||||||
|
|
||||||
|
如果没有通过`nonlocal`进行声明,那么对于s的赋值将会看作是`在innermost scope中创建了一个同名变量并进行赋值`,外部的变量值并不会改变。
|
||||||
|
|
||||||
|
通常来说,在函数定义内,scope为innermost scope,而在函数外则是global namespace,`类定义会新开一个namespace`。
|
||||||
|
|
||||||
|
##### global namespace
|
||||||
|
对于module中定义的function,其global namespace即是module namespace,无论函数在哪里被调用。
|
||||||
|
|
||||||
|
|
||||||
|
在python中,如果没有使用`global`或`nonlocal`,那么变量是只读的,对name的赋值永远会在innermost scope中。`del`语句则是从local scope对应的namespace中移除变量的绑定。
|
||||||
|
|
||||||
|
> 当在innermost scope中,如果只对外层变量进行读操作,那么无需使用`global`或是`nonlocal`;但是,如果想要修改外层变量,则需要使用`global`或者`nonlocal`,否则外层变量是只读的。
|
||||||
|
|
||||||
|
```py
|
||||||
|
def scope_test():
|
||||||
|
def do_local():
|
||||||
|
spam = "local spam"
|
||||||
|
|
||||||
|
def do_nonlocal():
|
||||||
|
nonlocal spam
|
||||||
|
spam = "nonlocal spam"
|
||||||
|
|
||||||
|
def do_global():
|
||||||
|
global spam
|
||||||
|
spam = "global spam"
|
||||||
|
|
||||||
|
spam = "test spam"
|
||||||
|
do_local()
|
||||||
|
print("After local assignment:", spam)
|
||||||
|
do_nonlocal()
|
||||||
|
print("After nonlocal assignment:", spam)
|
||||||
|
do_global()
|
||||||
|
print("After global assignment:", spam)
|
||||||
|
|
||||||
|
scope_test()
|
||||||
|
print("In global scope:", spam)
|
||||||
|
```
|
||||||
|
在上述示例中,返回结果如下:
|
||||||
|
```
|
||||||
|
After local assignment: test spam
|
||||||
|
After nonlocal assignment: nonlocal spam
|
||||||
|
After global assignment: nonlocal spam
|
||||||
|
In global scope: global spam
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user