Skip to content

Commit 9998b51

Browse files
committed
补充*.md、深入*.md、网络*.md:整体调整格式,如删除多余空行、整理代码块、修正标点符号。
1 parent 81f8808 commit 9998b51

11 files changed

+405
-608
lines changed
Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,89 @@
11
##Python深入01 特殊方法与多范式
22

3+
Python一切皆对象,但同时,Python还是一个多范式语言(multi-paradigm),你不仅可以使用面向对象的方式来编写程序,还可以用面向过程的方式来编写相同功能的程序(还有函数式、声明式等,我们暂不深入)。Python的多范式依赖于Python对象中的特殊方法(special method)。
34

4-
5+
特殊方法名的前后各有两个下划线。特殊方法又被成为魔法方法(magic method),定义了许多Python语法和表达方式,正如我们在下面的例子中将要看到的。当对象中定义了特殊方法的时候,Python也会对它们有“特殊优待”。比如定义了`__init__()`方法的类,会在创建对象的时候自动执行`__init__()`方法中的操作。
56

6-
Python一切皆对象,但同时,Python还是一个多范式语言(multi-paradigm),你不仅可以使用面向对象的方式来编写程序,还可以用面向过程的方式来编写相同功能的程序(还有函数式、声明式等,我们暂不深入)。Python的多范式依赖于Python对象中的特殊方法(special method)。
7-
8-
特殊方法名的前后各有两个下划线。特殊方法又被成为魔法方法(magic method),定义了许多Python语法和表达方式,正如我们在下面的例子中将要看到的。当对象中定义了特殊方法的时候,Python也会对它们有“特殊优待”。比如定义了`__init__()`方法的类,会在创建对象的时候自动执行`__init__()`方法中的操作。
9-
10-
(可以通过`dir()`来查看对象所拥有的特殊方法,比如`dir(1)`)
11-
12-
7+
(可以通过`dir()`来查看对象所拥有的特殊方法,比如`dir(1)`。)
138

149
##运算符
1510

1611
Python的运算符是通过调用对象的特殊方法实现的。比如:
12+
1713
```python
18-
'abc' + 'xyz' # 连接字符串
14+
'abc' + 'xyz' # 连接字符串
1915
```
16+
2017
实际执行了如下操作:
18+
2119
```python
2220
'abc'.__add__('xyz')
2321
```
24-
所以,在Python中,两个对象是否能进行加法运算,首先就要看相应的对象是否有`__add__()`方法。一旦相应的对象有`__add__()`方法,即使这个对象从数学上不可加,我们都可以用加法的形式,来表达`obj.__add__()`所定义的操作。在Python中,运算符起到简化书写的功能,但它依靠特殊方法实现。
2522

26-
Python不强制用户使用面向对象的编程方法。用户可以选择自己喜欢的使用方式(比如选择使用`+`符号,还是使用更加面向对象的`__add__()`方法)。特殊方法写起来总是要更费事一点
23+
所以,在Python中,两个对象是否能进行加法运算,首先就要看相应的对象是否有`__add__()`方法。
2724

28-
尝试下面的操作,看看效果,再想想它的对应运算符
25+
一旦相应的对象有`__add__()`方法,即使这个对象从数学上不可加,我们都可以用加法的形式,来表达`obj.__add__()`所定义的操作。
2926

30-
(1.8).__mul__(2.0)
27+
在Python中,运算符起到简化书写的功能,但它依靠特殊方法实现。
3128

32-
True.__or__(False)
29+
Python不强制用户使用面向对象的编程方法。用户可以选择自己喜欢的使用方式(比如选择使用`+`符号,还是使用更加面向对象的`__add__()`方法)。特殊方法写起来总是要更费事一点。
3330

34-
31+
尝试下面的操作,看看效果,再想想它的对应运算符:
32+
33+
```pytho
34+
(1.8).__mul__(2.0)
35+
True.__or__(False)
36+
```
3537

3638
##内置函数
3739

38-
与运算符类似,许多内置函数也都是调用对象的特殊方法。比如
40+
与运算符类似,许多内置函数也都是调用对象的特殊方法。比如:
41+
3942
```python
40-
len([1,2,3]) # 返回表中元素的总数
43+
len([1, 2, 3]) # 返回表中元素的总数
4144
```
42-
实际上做的是
45+
46+
实际上做的是:
47+
4348
```python
44-
[1,2,3].__len__()
49+
[1, 2, 3].__len__()
4550
```
51+
4652
相对与`__len__()`,内置函数`len()`也起到了简化书写的作用。
4753

48-
尝试下面的操作,想一下它的对应内置函数
54+
尝试下面的操作,想一下它的对应内置函数
4955

56+
```python
5057
(-1).__abs__()
51-
5258
(2.3).__int__()
59+
```
5360

54-
61+
##表(list)元素引用
5562

56-
##表(list)元素引用
63+
下面是我们常见的表元素引用方式:
5764

58-
下面是我们常见的表元素引用方式
5965
```python
6066
li = [1, 2, 3, 4, 5, 6]
6167
print(li[3])
6268
```
69+
6370
上面的程序运行到`li[3]`的时候,Python发现并理解`[]`符号,然后调用`__getitem__()`方法。
71+
6472
```python
6573
li = [1, 2, 3, 4, 5, 6]
6674
print(li.__getitem__(3))
6775
```
68-
尝试看下面的操作,想想它的对应
6976

70-
li.__setitem__(3, 0)
77+
尝试看下面的操作,想想它的对应:
7178

79+
```python
80+
li.__setitem__(3, 0)
7281
{'a':1, 'b':2}.__delitem__('a')
73-
82+
```
7483

7584
##函数
7685

77-
我们已经说过,在Python中,函数也是一种对象。实际上,任何一个有`__call__()`特殊方法的对象都被当作是函数。比如下面的例子:
86+
我们已经说过,在Python中,函数也是一种对象。实际上,任何一个有`__call__()`特殊方法的对象都被当作是函数。比如下面的例子
7887

7988
```python
8089
class SampleMore(object):
@@ -90,16 +99,10 @@ map(add, [2, 4, 5]) # Pass around function object
9099

91100
当然,我们还可以使用更“优美”的方式,想想是什么。
92101

93-
94-
95102
##总结
96103

97-
对于内置的对象来说(比如整数、表、字符串等),它们所需要的特殊方法都已经在Python中准备好了。而用户自己定义的对象也可以通过增加特殊方法,来实现自定义的语法。特殊方法比较靠近Python的底层,许多Python功能的实现都要依赖于特殊方法。我们将在以后看到更多的例子。
98-
99-
100-
101-
104+
对于内置的对象来说(比如整数、表、字符串等),它们所需要的特殊方法都已经在Python中准备好了。而用户自己定义的对象也可以通过增加特殊方法,来实现自定义的语法。特殊方法比较靠近Python的底层,许多Python功能的实现都要依赖于特殊方法。我们将在以后看到更多的例子。
102105

103-
大黄蜂,还是Camaro跑车
106+
###大黄蜂,还是Camaro跑车
104107

105-
Python的许多语法都是基于其面向对象模型的封装。对象模型是Python的骨架,是功能完备、火力强大的大黄蜂。但是Python也提供更加简洁的语法,让你使用不同的编程形态,从而在必要时隐藏一些面向对象的接口。正如我们看到的Camaro跑车,将自己威风的火药库收起来,提供方便人类使用的车门和座椅。
108+
Python的许多语法都是基于其面向对象模型的封装。对象模型是Python的骨架,是功能完备、火力强大的大黄蜂。但是Python也提供更加简洁的语法,让你使用不同的编程形态,从而在必要时隐藏一些面向对象的接口。正如我们看到的Camaro跑车,将自己威风的火药库收起来,提供方便人类使用的车门和座椅。
Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
#Python深入02 上下文管理器
2-
3-
4-
上下文管理器(context manager)是Python2.5开始支持的一种语法,用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存)。它的语法形式是`with...as...`
52

6-
3+
上下文管理器(context manager)是Python2.5开始支持的一种语法,用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用(比如为对象分配或者释放内存)。它的语法形式是`with...as...`
74

85
##关闭文件
96

107
我们会进行这样的操作:打开文件,读写,关闭文件。程序员经常会忘记关闭文件。上下文管理器可以在不需要文件的时候,自动关闭文件。
118

129
下面我们看一下两段程序:
10+
1311
```python
1412
# without context manager
1513
f = open("new.txt", "w")
@@ -18,66 +16,66 @@ f.write("Hello World!")
1816
f.close()
1917
print(f.closed)
2018
```
19+
2120
以及:
21+
2222
```python
2323
# with context manager
2424
with open("new.txt", "w") as f:
2525
print(f.closed)
2626
f.write("Hello World!")
2727
print(f.closed)
2828
```
29-
两段程序实际上执行的是相同的操作。我们的第二段程序就使用了上下文管理器 (`with...as...`)。上下文管理器有隶属于它的程序块。当隶属的程序块执行结束的时候(也就是不再缩进),上下文管理器自动关闭了文件 (我们通过`f.closed`来查询文件是否关闭)。我们相当于使用缩进规定了文件对象`f`的使用范围。
3029

31-
30+
两段程序实际上执行的是相同的操作。我们的第二段程序就使用了上下文管理器(`with...as...`)。
3231

33-
上面的上下文管理器基于`f`对象的`__exit__()`特殊方法(还记得我们如何利用特殊方法来实现各种语法?参看特殊方法与多范式)。当我们使用上下文管理器的语法时,我们实际上要求Python在进入程序块之前调用对象的`__enter__()`方法,在结束程序块的时候调用`__exit__()`方法。对于文件对象f来说,它定义了`__enter__()``__exit__()`方法(可以通过`dir(f)`看到)。在`f``__exit__()`方法中,有`self.close()`语句。所以在使用上下文管理器时,我们就不用明文关闭`f`文件了
32+
上下文管理器有隶属于它的程序块。当隶属的程序块执行结束的时候(也就是不再缩进),上下文管理器自动关闭了文件(我们通过`f.closed`来查询文件是否关闭)。我们相当于使用缩进规定了文件对象`f`的使用范围
3433

35-
34+
上面的上下文管理器基于`f`对象的`__exit__()`特殊方法(还记得我们如何利用特殊方法来实现各种语法?参看特殊方法与多范式)。
35+
36+
当我们使用上下文管理器的语法时,我们实际上要求Python在进入程序块之前调用对象的`__enter__()`方法,在结束程序块的时候调用`__exit__()`方法。
37+
38+
对于文件对象f来说,它定义了`__enter__()``__exit__()`方法(可以通过`dir(f)`看到)。在`f``__exit__()`方法中,有`self.close()`语句。所以在使用上下文管理器时,我们就不用明文关闭`f`文件了。
3639

3740
##自定义
3841

3942
任何定义了`__enter__()``__exit__()`方法的对象都可以用于上下文管理器。文件对象`f`是内置对象,所以`f`自动带有这两个特殊方法,不需要自定义。
4043

4144
下面,我们自定义用于上下文管理器的对象,就是下面的`myvow`
4245

43-
44-
4546
```python
4647
# customized object
47-
4848
class VOW(object):
4949
def __init__(self, text):
5050
self.text = text
5151
def __enter__(self):
5252
self.text = "I say: " + self.text # add prefix
5353
return self # note: return an object
54-
def __exit__(self,exc_type,exc_value,traceback):
54+
def __exit__(self, exc_type, exc_value, traceback):
5555
self.text = self.text + "!" # add suffix
5656

57-
5857
with VOW("I'm fine") as myvow:
5958
print(myvow.text)
6059

6160
print(myvow.text)
6261
```
63-
6462

65-
我们的运行结果如下:
63+
我们的运行结果如下
6664

65+
```quote
6766
I say: I'm fine
6867
I say: I'm fine!
68+
```
6969

70-
我们可以看到,在进入上下文和离开上下文时,对象的text属性发生了改变(最初的`text`属性是`"I'm fine"`)。
71-
72-
`__enter__()`返回一个对象。上下文管理器会使用这一对象作为`as`所指的变量,也就是`myvow`。在`__enter__()`中,我们为`myvow.text`增加了前缀 (`"I say: "`)。在`__exit__()`中,我们为`myvow.text`增加了后缀(`"!"`)。
70+
我们可以看到,在进入上下文和离开上下文时,对象的text属性发生了改变(最初的`text`属性是`"I'm fine"`)。
7371

74-
注意: `__exit__()`中有四个参数。当程序块中出现异常(`exception`),`__exit__()`的参数中`exc_type`, `exc_value`, `traceback`用于描述异常。我们可以根据这三个参数进行相应的处理。如果正常运行结束,这三个参数都是`None`。在我们的程序中,我们并没有用到这一特性
72+
`__enter__()`返回一个对象。上下文管理器会使用这一对象作为`as`所指的变量,也就是`myvow`。在`__enter__()`中,我们为`myvow.text`增加了前缀(`"I say: "`)。在`__exit__()`中,我们为`myvow.text`增加了后缀(`"!"`
7573

76-
74+
注意:`__exit__()`中有四个参数。当程序块中出现异常(`exception`),`__exit__()`的参数中`exc_type``exc_value``traceback`用于描述异常。我们可以根据这三个参数进行相应的处理。如果正常运行结束,这三个参数都是`None`。在我们的程序中,我们并没有用到这一特性。
7775

7876
##总结:
7977

80-
通过上下文管理器,我们控制对象在程序不同区间的特性。上下文管理器(`with EXPR as VAR`)大致相当于如下流程:
78+
通过上下文管理器,我们控制对象在程序不同区间的特性。上下文管理器`with EXPR as VAR`大致相当于如下流程
8179

8280
```python
8381
# with EXPR as VAR:
@@ -89,4 +87,5 @@ try:
8987
finally:
9088
VAR.__exit__()
9189
```
92-
由于上下文管理器带来的便利,它是一个值得使用的工具。
90+
91+
由于上下文管理器带来的便利,它是一个值得使用的工具。

0 commit comments

Comments
 (0)