重新修订 6 - 8 章节

pull/30/head
TwoWater 2019-10-09 17:42:48 +08:00
parent 54be4f5f6d
commit 95ad977818
40 changed files with 1219 additions and 474 deletions

View File

@ -2,7 +2,7 @@
上一篇文章出现了个明显的知识点错误,不过感谢有个网友的提出,及时进行了修改。也希望各位多多包涵。
(2019年09月01日15:28:00) 在修改文章的时候,发现自己两年前写的像屎一样, 忍不住还在群里吐槽一番。
>注:(2019年09月01日15:28:00) 在修改文章的时候,发现自己两年前写的像屎一样, 忍不住还在群里吐槽一番。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-01-072923.png)

View File

@ -1,12 +1,31 @@
# 二、循环语句 #
一般编程语言都有循环语句,循环语句允许我们执行一个语句或语句组多次。
## 1、什么是循环语句 ##
一般编程语言都有循环语句,为什么呢?
那就问一下自己,我们弄程序是为了干什么?
那肯定是为了方便我们工作,优化我们的工作效率啊。
而计算机和人类不同,计算机不怕苦也不怕累,也不需要休息,可以一直做。
你要知道,计算机最擅长就是做重复的事情。
所以这时候需要用到循环语句,循环语句允许我们执行一个语句或语句组多次。
循环语句的一般形式如下:
![python循环语句](http://upload-images.jianshu.io/upload_images/2136918-eaaae2fbfec3330f?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
Python 提供了 for 循环和 while 循环,当然还有一些控制循环的语句:
在 Python 提供了 for 循环和 while 循环。
这里又有一个问题了,如果我想让他运行了一百次之后停止,那该怎么做呢?
这时候需要用到一些控制循环的语句:
|循环控制语句|描述|
|------|------|
@ -14,28 +33,210 @@ Python 提供了 for 循环和 while 循环,当然还有一些控制循环的
|continue|在语句块执行过程中终止当前循环,跳出该次循环,执行下一次循环|
|pass|pass 是空语句,是为了保持程序结构的完整性|
这些控制语句是为了让我们告诉程序什么时候停止,什么时候不运行这次循环。
## 1、While 循环语句 ##
## 2、 for 循环语句 ##
我们先来看下 for 循环语句。
它的流程图基本如下:
![for循环的流程图](http://upload-images.jianshu.io/upload_images/2136918-a0728c1c488238af?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
基本的语法格式:
```python
for iterating_var in sequence:
statements(s)
```
那么我们根据他的基本语法格式,随便写个例子测试一下:
```python
count = 1
sum = 0
while (count <= 100):
sum = sum + count
count = count + 1
print(sum)
for letter in 'Hello 两点水':
print(letter)
```
输出的结果:
输出的结果如下:
```txt
H
e
l
l
o
```
从打印结果来看,它就是把字符串 `Hello 两点水` 一个一个字符的打印出来。
那如果我们把字符串换为字典 dict 呢?
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-094741.png)
你会发现只打印了字典 dict 中的每一个 key 值。
很多时候,我都是建议大家学到一个新的知识点,都多去尝试。
你尝试一遍,自己观察出来的结论,好过别人说十遍。
如果你不知道怎么去试?
可以根据我们的例子举一反三,比如上面的 for 循环,试了字符串,字典,那我们之前学的基本数据类型还有什么呢?
不记得可以再返回去看看,可以把所有的基本类型都拿去尝试一下。
比如,你试了之后,会发现整数和浮点数是不可以直接放在 for 循环里面的。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-095313.png)
## 3、 range() 函数 ##
for 循环还常常和 range() 函数搭配使用的。
如果不知道 range() 函数 , 我们直接通过一段程序来理解。
```python
for i in range(3):
print(i)
```
打印的结果为:
```
0
1
2
```
可见,打印了 0 到 3 。
使用 range(x) 函数,就可以生成一个从 0 到 x-1 的整数序列。
如果是 `range(a,b)` 函数,你可以生成了一个左闭右开的整数序列。
其实例子中的 `range(3)` 可以写成 `range(0,3)`, 结果是一样的。
其实使用 range() 函数,我们更多是为了把一段代码重复运行 n 次。
这里提个问题,你仔细观察 range() 函数,上面说到的不管是 1 个参数的,还是 2 个参数的都有什么共同的特点?
不知道你们有没有发现,他都是每次递增 1 的。
`range(3)` 就是 0 12 ,每次递增 1 。
`range(3,6)` 就是 3 4 5 ,也是每次递增 1 的。
那能不能每次不递增 1 呢?
比如我想递增 2 呢?
在程序的编写中,肯定会遇到这样的需求的。而 python 发展至今range 函数肯定也会有这种功能。
所以 range 函数还有一个三个参数的。
比如 `range(0,10,2) ` , 它的意思是:从 0 数到 10不取 10 ),每次间隔为 2 。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-09-065854.png)
## 4、While 循环语句 ##
While 循环和 for 循环的作用是一样的。
我们先来看看 While 循环语句的样子。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-083137.png)
程序输出的结果是:
```txt
5050
```
当然 while 语句时还有另外两个重要的命令 continuebreak 来跳过循环continue 用于跳过该次循环break 则是用于退出循环
这个例子是计算 1 到 100 所有整数的和。
比如,上面的例子是计算 1 到 100 所有整数的和,当我们需要判断 sum 大于 1000 的时候,不在相加时,可以用到 break ,退出整个循环
## 5、for 循环和 whlie 循环的区别 ##
之前也提到过了,如果一种语法能表示一个功能,那没必要弄两种语法来表示。
竟然都是循环for 循环和 while 循环肯定有他们的区别的。
那什么时候才使用 for 循环和 while 循环呢?
* for 循环主要用在迭代可迭代对象的情况。
* while 循环主要用在需要满足一定条件为真,反复执行的情况。
(死循环+break 退出等情况。)
* 部分情况下for 循环和 while 循环可以互换使用。
例如:
```python
for i in range(0, 10):
print(i)
i = 0
while i < 10:
print(i)
i = i + 1
```
虽然打印的结果是一样的,但是细细品味你会发现,他们执行的顺序和知道的条件是不同的。
## 6、嵌套循环 ##
循环语句和条件语句一样,都是可以嵌套的。
具体的语法如下:
**for 循环嵌套语法**
```python
for iterating_var in sequence:
for iterating_var in sequence:
statements(s)
statements(s)
```
**while 循环嵌套语法**
```python
while expression:
while expression:
statement(s)
statement(s)
```
除此之外,你也可以在循环体内嵌入其他的循环体,如在 while 循环中可以嵌入 for 循环, 反之,你可以在 for 循环中嵌入 while 循环
比如:
当我们需要判断 sum 大于 1000 的时候,不在相加时,可以用到 break ,退出整个循环。
```python
count = 1
@ -74,68 +275,7 @@ print(sum)
2500
```
在 Python 的 while 循环中,还可以使用 else 语句while … else 在循环条件为 false 时执行 else 语句块
比如:
```python
count = 0
while count < 5:
print (count)
count = count + 1
else:
print (count)
```
输出的结果:
```txt
0
1
2
3
4
5
```
## 2、 for 循环语句 ##
for循环可以遍历任何序列的项目如一个列表或者一个字符串
它的流程图基本如下:
![for循环的流程图](http://upload-images.jianshu.io/upload_images/2136918-a0728c1c488238af?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
基本的语法格式:
```python
for iterating_var in sequence:
statements(s)
```
实例:
```python
for letter in 'Hello 两点水':
print(letter)
```
输出的结果如下:
```txt
H
e
l
l
o
```
有 while … else 语句,当然也有 for … else 语句啦for 中的语句和普通的没有区别else 中的语句会在循环正常执行完(即 for 不是通过 break 跳出而中断的的情况下执行while … else 也是一样。
还有:
```python
for num in range(10,20): # 迭代 10 到 20 之间的数字
@ -163,28 +303,11 @@ for num in range(10,20): # 迭代 10 到 20 之间的数字
19 是一个质数
```
## 3、嵌套循环 ##
Python 语言允许在一个循环体里面嵌入另一个循环。上面的实例也是使用了嵌套循环的,这里就不给出实例了
当然,这里还用到了 `for … else` 语句
具体的语法如下:
其实 for 循环中的语句和普通的没有区别else 中的语句会在循环正常执行完(即 for 不是通过 break 跳出而中断的)的情况下执行。
**for 循环嵌套语法**
当然有 `for … else` ,也会有 `while … else` 。他们的意思都是一样的。
```python
for iterating_var in sequence:
for iterating_var in sequence:
statements(s)
statements(s)
```
**while 循环嵌套语法**
```python
while expression:
while expression:
statement(s)
statement(s)
```
除此之外,你也可以在循环体内嵌入其他的循环体,如在 while 循环中可以嵌入 for 循环, 反之,你可以在 for 循环中嵌入 while 循环

View File

@ -1,14 +1,19 @@
# 一、条件语句 #
## 1、什么是条件语句 ##
Python 条件语句跟其他语言基本一致的,都是通过一条或多条语句的执行结果( True 或者 False )来决定执行的代码块。
Python 程序语言指定任何非 0 和非空null值为 True0 或者 null为 False。
Python 程序语言指定任何非 0 和非空null值为 True0 或者 null 为 False。
执行的流程图如下:
![if语句流程图](http://upload-images.jianshu.io/upload_images/2136918-4ee2486190450a1a?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## 1、if 语句的基本形式 ##
## 2、if 语句的基本形式 ##
Python 中if 语句的基本形式如下:
@ -19,7 +24,7 @@ else
执行语句……
```
前面也提到过Python 语言有着严格的缩进要求,因此这里也需要注意缩进,也不要少写了冒号 `:`
之前的章节也提到过Python 语言有着严格的缩进要求,因此这里也需要注意缩进,也不要少写了冒号 `:`
if 语句的判断条件可以用>(大于)、<(小于)、==(等于)、>=(大于等于)、<=(小于等于)来表示其关系。
@ -43,7 +48,7 @@ else :
不及格
```
上面也说,非零数值、非空字符串、非空 list 等判断为True否则为False。因此也可以这样写
上面也说,非零数值、非空字符串、非空 list 等,判断为 True否则为 False。因此也可以这样写
```python
num = 6
@ -51,7 +56,27 @@ if num :
print('Hello Python')
```
## 2、if 语句多个判断条件的形式 ##
输出的结果如下:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-072713.png)
可见,把结果打印出来了。
那如果我们把 `num ` 改为空字符串呢?
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-072941.png)
很明显,空字符串是为 False 的,不符合条件语句,因此不会执行到 `print('Hello Python')` 这段代码。
还有再啰嗦一点,提醒一下,在条件判断代码中的冒号 `:` 后、下一行内容是一定要缩进的。不缩进是会报错的。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-073432.png)
冒号和缩进是一种语法。它会帮助 Python 区分代码之间的层次,理解条件执行的逻辑及先后顺序。
## 3、if 语句多个判断条件的形式 ##
有些时候,我们的判断语句不可能只有两个,有些时候需要多个,比如上面的例子中大于 60 的为及格,那我们还要判断大于 90 的为优秀,在 80 到 90 之间的良好呢?
@ -94,9 +119,21 @@ else :
良好
```
## 3、if 语句多个条件同时判断 ##
Python 不像 Java 有 switch 语句,所以多个条件判断,只能用 elif 来实现,但是有时候需要多个条件需同时判断时,可以使用 or (或),表示两个条件有一个成立时判断条件成功;使用 and (与)时,表示只有两个条件同时成立的情况下,判断条件才成功。
## 4、if 语句多个条件同时判断 ##
有时候我们会遇到多个条件的时候该怎么操作呢?
比如说要求 java 和 python 的考试成绩要大于 80 分的时候才算优秀,这时候该怎么做?
这时候我们可以结合 `or``and` 来使用。
or (或)表示两个条件有一个成立时判断条件成功
and (与)表示只有两个条件同时成立的情况下,判断条件才成功。
例如:
```python
# -*-coding:utf-8-*-
@ -122,3 +159,20 @@ if ( java >= 80 and java < 90 ) or ( python >= 80 and python < 90):
```
注意if 有多个条件时可使用括号来区分判断的先后顺序,括号中的判断优先执行,此外 and 和 or 的优先级低于 >(大于)、<(小于)等判断符号,即大于和小于在没有括号的情况下会比与或要优先判断。
## 5、if 嵌套 ##
if 嵌套是指什么呢?
就跟字面意思差不多,指 if 语句中可以嵌套 if 语句。
比如上面说到的例子,也可以用 if 嵌套来写。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-080557.png)
当然这只是为了说明 if 条件语句是可以嵌套的。如果是这个需求,我个人还是不太建议这样使用 if 嵌套的,因为这样代码量多了,而且嵌套太多,也不方便阅读代码。

View File

@ -1,10 +1,16 @@
# 前言 #
第一次建学习群,而且是 Python 的学习群,虽然之前深入学习和工作都是 Android 相关的,最近学起来 Python ,真的很好玩,所以创了个微信群,希望童鞋们进群学习讨论。也可以直接加我微`androidwed`拉进群。也欢迎大家在 [Gitbook](https://www.readwithu.com/) 中提出文章的不足
通常都听到别人说,计算机很牛逼,很聪明,其实计算机一点都不聪明,光是你要跟他沟通,都会气 shi 你,聪明的是在写程序的你
![Python学习群](http://upload-images.jianshu.io/upload_images/2136918-f3f0c60ce12e5a92?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
写程序就是跟计算机沟通,告诉它要做什么。
竟然是这样,那么肯定缺少不了一些沟通逻辑。比如你要告诉计算机在什么情况下做什么?或者在哪个时间点做什么?
这都需要用到逻辑判断。这一章节,主要就是说这个。
# 目录 #
![草根学Python 条件语句和循环语句](http://upload-images.jianshu.io/upload_images/2136918-32902eec93d9ffc1?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-09-%E6%9D%A1%E4%BB%B6%E8%AF%AD%E5%8F%A5%E5%92%8C%E5%BE%AA%E7%8E%AF%E8%AF%AD%E5%8F%A5.png)

View File

@ -0,0 +1,101 @@
# 一、Python 自定义函数的基本步骤 #
## 1、什么是函数 ##
函数,其实我们一开始学 Python 的时候就接触过。
不过我们使用的大多数都是 Python 的内置函数。
比如基本每个章节都会出现的 `print()` 函数。
而现在,我们主要学习的是自定义函数。
**各位有没有想过为什么需要函数呢?**
如果要想回答这个问题,我们需要先了解函数是什么?
函数就是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
没错,函数其实就是把代码抽象出来的代码段。
那为什么要抽象出来呢?
**方便我们使用,方便我们重复使用。**
**函数的本质就是我们把一些数据喂给函数,让他内部消化,然后吐出你想要的东西,至于他怎么消化的,我们不需要知道,它内部解决。**
怎么理解这句话呢?
举个例子,好比每次用到的 print 函数,我们都知道这个函数的作用是可以把我们的数据输出到控制台,让我们看到。所以 `print('两点水')` , 我们想打印 `两点水` 出来,就把 `两点水` 这个数据喂给 `print` 函数,然后他就直接把结果打印到控制台上了。
## 2、怎么自定义函数 ##
怎么自定义函数?
要知道怎么定义函数,就要知道函数的组成部分是怎样的。
```python
def 函数名(参数1参数2....参数n):
函数体
return 语句
```
这就是 Python 函数的组成部分。
所以自定义函数,基本有以下规则步骤:
* 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()
* 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数
* 函数的第一行语句可以选择性地使用文档字符串(用于存放函数说明)
* 函数内容以冒号起始,并且缩进
* return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的 return 相当于返回 None。
语法示例:
```python
def functionname( parameters ):
"函数_文档字符串"
function_suite
return [expression]
```
实例:
1. def 定义一个函数,给定一个函数名 sum
2. 声明两个参数 num1 和 num2
3. 函数的第一行语句进行函数说明:两数之和
4. 最终 return 语句结束函数,并返回两数之和
```python
def sum(num1,num2):
"两数之和"
return num1+num2
# 调用函数
print(sum(5,6))
```
输出结果:
```python
11
```

View File

@ -1,6 +1,8 @@
# 、函数返回值 #
# 、函数返回值 #
通过上面的学习,可以知道通过 return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None。
通过上面的学习,可以知道通过 return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。
**不带参数值的 return 语句返回 None。**
具体示例:
@ -51,4 +53,16 @@ print (tuple1)
(2.0, 1)
```
认真观察就可以发现,尽管从第一个输出值来看,返回了多个值,实际上是先创建了一个元组然后返回的。回忆一下,元组是可以直接用逗号来创建的,观察例子中的 ruturn ,可以发现实际上我们使用的是逗号来生成一个元组。
认真观察就可以发现,尽管从第一个输出值来看,返回了多个值,实际上是先创建了一个元组然后返回的。
回忆一下,元组是可以直接用逗号来创建的,观察例子中的 ruturn ,可以发现实际上我们使用的是逗号来生成一个元组。
Python 语言中的函数返回值可以是多个而其他语言都不行这是Python 相比其他语言的简便和灵活之处。
**Python 一次接受多个返回值的数据类型就是元组。**
不知道此刻你还记不记得元组的相关知识,如果不记得,建议现在立刻写几个例子回忆一下,比如如何获取元组的第一个元素出来。

View File

@ -1,9 +1,28 @@
# 、函数的参数 #
# 、函数的参数 #
## 1、默认值参数 ##
## 1、函数的参数类型 ##
设置与传递参数是函数的重点,而 Python 的函数对参数的支持非常的灵活。
主要的参数类型有:默认参数、关键字参数(位置参数)、不定长参数。
下面我们将一一了解这几种参数。
## 2、默认参数 ##
有时候,我们自定义的函数中,如果调用的时候没有设置参数,需要给个默认值,这时候就需要用到默认值参数了。
默认参数,只要在构造函数参数的时候,给参数赋值就可以了
例如:
```python
# -*- coding: UTF-8 -*-
@ -27,9 +46,17 @@ print_user_info( '三点水' , 25 )
昵称:三点水 年龄25 性别:男
```
可以看到,当你设置了默认参数的时候,在调用函数的时候,不传该参数,就会使用默认值。但是这里需要注意的一点是:**只有在形参表末尾的那些参数可以有默认参数值**也就是说你不能在声明函数形参的时候先声明有默认值的形参而后声明没有默认值的形参。这是因为赋给形参的值是根据位置而赋值的。例如def func(a, b=1) 是有效的,但是 def func(a=1, b) 是 无效 的。
从输出结果可以看到,当你设置了默认参数的时候,在调用函数的时候,不传该参数,就会使用默认值。
默认值参数就这样结束了吗?还没有的,细想一下,如果参数中是一个可修改的容器比如一个 lsit (列表)或者 dict (字典),那么我们使用什么来作为默认值呢?我们可以使用 None 作为默认值。就像下面这个例子一样:
但是这里需要注意的一点是:**只有在形参表末尾的那些参数可以有默认参数值**,也就是说你不能在声明函数形参的时候,先声明有默认值的形参而后声明没有默认值的形参。
这是因为赋给形参的值是根据位置而赋值的。例如def func(a, b=1) 是有效的,但是 def func(a=1, b) 是 无效 的。
默认值参数就这样结束了吗?
还没有的,细想一下,如果参数中是一个可修改的容器比如一个 lsit (列表)或者 dict (字典),那么我们使用什么来作为默认值呢?
我们可以使用 None 作为默认值。就像下面这个例子一样:
```python
# 如果 b 是一个 list ,可以使用 None 作为默认值
@ -39,13 +66,21 @@ def print_info( a , b = None ):
return;
```
认真看下例子,会不会有这样的疑问呢?在参数中我们直接 `b=[]` 不就行了吗?也就是写成下面这个样子:
认真看下例子,会不会有这样的疑问呢?在参数中我们直接 `b=[]` 不就行了吗?
也就是写成下面这个样子:
```python
def print_info( a , b = [] ):
return;
```
对不对呢?运行一下也没发现错误啊,可以这样写吗?这里需要特别注意的一点:**默认参数的值是不可变的对象比如None、True、False、数字或字符串**,如果你像上面的那样操作,当默认值在其他地方被修改后你将会遇到各种麻烦。这些修改会影响到下次调用这个函数时的默认值。
对不对呢?
运行一下也没发现错误啊,可以这样写吗?
这里需要特别注意的一点:**默认参数的值是不可变的对象比如None、True、False、数字或字符串**,如果你像上面的那样操作,当默认值在其他地方被修改后你将会遇到各种麻烦。
这些修改会影响到下次调用这个函数时的默认值。
示例如下:
@ -73,7 +108,9 @@ print_info(2)
认真观察,你会发现第二次输出的值根本不是你想要的,因此切忌不能这样操作。
还有一点,有时候我就是不想要默认值啊,只是想单单判断默认参数有没有值传递进来,那该怎么办?我们可以这样做:
还有一点,有时候我就是不想要默认值啊,只是想单单判断默认参数有没有值传递进来,那该怎么办?
我们可以这样做:
```python
_no_value =object()
@ -83,15 +120,25 @@ def print_info( a , b = _no_value ):
print('b 没有赋值')
return;
```
这里的 `object` 是python中所有类的基类。 你可以创建 `object` 类的实例,但是这些实例没什么实际用处,因为它并没有任何有用的方法, 也没有任何实例数据(因为它没有任何的实例字典,你甚至都不能设置任何属性值)。 你唯一能做的就是测试同一性。也正好利用这个特性,来判断是否有值输入。
## 2、关键字参数 ##
这里的 `object` 是 python 中所有类的基类。 你可以创建 `object` 类的实例,但是这些实例没什么实际用处,因为它并没有任何有用的方法, 也没有任何实例数据(因为它没有任何的实例字典,你甚至都不能设置任何属性值)。 你唯一能做的就是测试同一性。也正好利用这个特性,来判断是否有值输入。
在 Python 中,可以通过参数名来给函数传递参数,而不用关心参数列表定义时的顺序,这被称之为关键字参数。使用关键参数有两个优势
一、由于我们不必担心参数的顺序,使用函数变得更加简单了。
二、假设其他参数都有默认值,我们可以只给我们想要的那些参数赋值
## 3、关键字参数位置参数 ##
一般情况下,我们需要给函数传参的时候,是要按顺序来的,如果不对应顺序,就会传错值。
不过在 Python 中,可以通过参数名来给函数传递参数,而不用关心参数列表定义时的顺序,这被称之为关键字参数。
使用关键参数有两个优势
* 由于我们不必担心参数的顺序,使用函数变得更加简单了。
* 假设其他参数都有默认值,我们可以只给我们想要的那些参数赋值
具体看例子:
```python
# -*- coding: UTF-8 -*-
@ -117,10 +164,19 @@ print_user_info( name = '两点水' ,sex = '女', age = 18 )
昵称:两点水 年龄18 性别:女
```
## 3、不定长参数 ##
有时我们在设计函数接口的时候可会需要可变长的参数。也就是说我们事先无法确定传入的参数个数。Python 提供了一种元组的方式来接受没有直接定义的参数。这种方式在参数前边加星号 `*` 。如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。
## 4、不定长参数 ##
或许有些时候,我们在设计函数的时候,我们有时候无法确定传入的参数个数。
那么我们就可以使用不定长参数。
Python 提供了一种元组的方式来接受没有直接定义的参数。这种方式在参数前边加星号 `*`
如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。
例如:
@ -146,10 +202,12 @@ print_user_info( '两点水' ,18 , '女', '打篮球','打羽毛球','跑步')
昵称:两点水 年龄18 性别:女 爱好:('打篮球', '打羽毛球', '跑步')
```
通过输出的结果可以知道,`*hobby`是可变参数,且 hobby其实就是一个 tuple (元祖)
通过输出的结果可以知道,`*hobby`是可变参数,且 hobby 其实就是一个 tuple (元祖)
可变长参数也支持关键参数,没有被定义的关键参数会被放到一个字典里。这种方式即是在参数前边加 `**`,更改上面的示例如下:
可变长参数也支持关键字参数(位置参数),没有被定义的关键参数会被放到一个字典里。
这种方式即是在参数前边加 `**`,更改上面的示例如下:
```python
@ -177,7 +235,8 @@ print_user_info( name = '两点水' , age = 18 , sex = '女', hobby = ('打篮
通过对比上面的例子和这个例子,可以知道,`*hobby`是可变参数,且 hobby其实就是一个 tuple (元祖),`**hobby`是关键字参数,且 hobby 就是一个 dict (字典)
## 4、只接受关键字参数 ##
## 5、只接受关键字参数 ##
关键字参数使用起来简单,不容易参数出错,那么有些时候,我们定义的函数希望某些参数强制使用关键字参数传递,这时候该怎么办呢?
@ -201,6 +260,7 @@ print_user_info( name = '两点水' ,age = 18 , sex = '女' )
print_user_info('两点水',age='22',sex='男')
```
通过例子可以看,如果 `age` , `sex` 不适用关键字参数是会报错的。
通过例子可以看,如果 `age` , `sex` 不使用关键字参数是会报错的。
很多情况下,使用强制关键字参数会比使用位置参数表意更加清晰,程序也更加具有可读性。使用强制关键字参数也会比使用 `**kw` 参数更好且强制关键字参数在一些更高级场合同样也很有用。
很多情况下,使用强制关键字参数会比使用位置参数表意更加清晰,程序也更加具有可读性。使用强制关键字参数也会比使用 `**kw` 参数更好且强制关键字参数在一些更高级场合同样也很有用。

View File

@ -1,4 +1,4 @@
# 、函数传值问题 #
# 、函数传值问题 #
先看一个例子:
@ -18,12 +18,17 @@ print( b )
1
```
这里可能有些人会有疑问,为啥不是通过函数`chagne_number`更改了 b
的值吗?为啥没有变化,输出的结果还是 1 ,这个问题很多编程语言都会讲到,原理解释也是差不多的。
先看看运行的结果?
想一下为什么打印的结果是 1 ,而不是 1000
其实把问题归根结底就是,为什么通过函数 `chagne_number` 没有更改到 b 的值?
这个问题很多编程语言都会讲到,原理解释也是差不多的。
这里主要是函数参数的传递中,传递的是类型对象,之前也介绍了 Python 中基本的数据类型等。而这些类型对象可以分为可更改类型和不可更改的类型
在 Python 中字符串整形浮点型tuple 是不可更改的对象,而 list dict 等是可以更改的对象。
**在 Python 中字符串整形浮点型tuple 是不可更改的对象,而 list dict 等是可以更改的对象。**
例如:
@ -78,7 +83,6 @@ def chagne_list( b ):
b = [1,2,3,4,5]
chagne_list( b )
print( '最后输出 b 的值:{}' .format( b ) )
```
输出的结果:
@ -88,3 +92,5 @@ print( '最后输出 b 的值:{}' .format( b ) )
函数中 b 赋值后的值:[1, 2, 3, 4, 5, 1000]
最后输出 b 的值:[1, 2, 3, 4, 5, 1000]
```

View File

@ -1,6 +1,8 @@
# 五、匿名函数 #
有没有想过定义一个很短的回调函数,但又不想用 `def` 的形式去写一个那么长的函数,那么有没有快捷方式呢?答案是有的。
有没有想过定义一个很短的回调函数,但又不想用 `def` 的形式去写一个那么长的函数,那么有没有快捷方式呢?
答案是有的。
python 使用 lambda 来创建匿名函数,也就是不再使用 def 语句这样标准的形式定义一个函数。
@ -57,4 +59,5 @@ print( sum2( 1 ) )
10001
```
这主要在于 lambda 表达式中的 num2 是一个自由变量,在运行时绑定值,而不是定义时就绑定,这跟函数的默认值参数定义是不同的。所以建议还是遇到这种情况还是使用第一种解法。
**这主要在于 lambda 表达式中的 num2 是一个自由变量,在运行时绑定值,而不是定义时就绑定,这跟函数的默认值参数定义是不同的。所以建议还是遇到这种情况还是使用第一种解法。**

View File

@ -0,0 +1,13 @@
# 前言 #
函数这个章节内容有点多,对于新手,也有些不好理解。建议各位多看几篇,多敲几次代码。
最后这是我的个人微信号,大家可以添加一下,交个朋友,一起讨论。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-07-070041.jpg)
# 目录 #
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-07-%E5%87%BD%E6%95%B0.png)

View File

@ -4,7 +4,9 @@
比如在 Java 中,我们通过 List 集合的下标来遍历 List 集合中的元素,在 Python 中,给定一个 list 或 tuple我们可以通过 for 循环来遍历这个 list 或 tuple ,这种遍历就是迭代。
可是Python 的 `for` 循环抽象程度要高于 Java 的 `for` 循环的,为什么这么说呢?因为 Python 的 `for` 循环不仅可以用在 list 或tuple 上,还可以作用在其他可迭代对象上。也就是说,只要是可迭代的对象,无论有没有下标,都是可以迭代的。
可是Python 的 `for` 循环抽象程度要高于 Java 的 `for` 循环的,为什么这么说呢?因为 Python 的 `for` 循环不仅可以用在 list 或tuple 上,还可以作用在其他可迭代对象上。
也就是说,只要是可迭代的对象,无论有没有下标,都是可以迭代的。
比如:
@ -59,3 +61,5 @@ name age sex
2 b
3 c
```

View File

@ -18,9 +18,13 @@ print(list1)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
```
这个其实在之前也有提到过:比如有个例子,打印九九乘法表,用这个方法其实就几句代码就可以了,具体可以看之前的这个章节:[条件语句和循环语句综合实例](https://www.readwithu.com/python5/Example.html)
这个其实在之前也有提到过,打印九九乘法表,用这个方法其实就几句代码就可以了,具体可以看之前的这个章节:[条件语句和循环语句综合实例](../python5/Example.md)
但是,如果用到 list 生成式,可以一句代码就生成九九乘法表了。具体看代码:
但是,如果用到 list 生成式,可以一句代码就生成九九乘法表了。
你没听错,就是一句代码。
具体实现:
```python
print('\n'.join([' '.join ('%dx%d=%2d' % (x,y,x*y) for x in range(1,y+1)) for y in range(1,10)]))
@ -102,3 +106,5 @@ print(lsit1)
```
其实知道了 list 生成式是怎样组合的,就不难理解这个东西了。因为 list 生成式只是把之前学习的知识点进行了组合,换成了一种更简洁的写法而已。

View File

@ -2,15 +2,21 @@
## 1、为什么需要生成器 ##
通过上面的学习,可以知道列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含 1000 万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
通过上面的学习,可以知道列表生成式,我们可以直接创建一个列表。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的 list从而节省大量的空间。在 Python 中这种一边循环一边计算的机制称为生成器generator。
但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含 1000 万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
**所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?**
这样就不必创建完整的 list从而节省大量的空间。
**在 Python 中这种一边循环一边计算的机制称为生成器generator。**
在 Python 中,使用了 yield 的函数被称为生成器generator
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息返回yield的值。并在下一次执行 next()方法时从当前位置继续运行。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值。并在下一次执行 next()方法时从当前位置继续运行。
那么如何创建一个生成器呢?
@ -31,7 +37,11 @@ print(gen)
<generator object <genexpr> at 0x0000000002734A40>
```
创建 List 和 generator 的区别仅在于最外层的 `[]``()` 。但是生成器并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生” ( yield ) 出来。 生成器表达式使用了“惰性计算” ( lazy evaluation也有翻译为“延迟求值”我以为这种按需调用 call by need 的方式翻译为惰性更好一些),只有在检索时才被赋值( evaluated ),所以在列表比较长的情况下使用内存上更有效。
创建 List 和 generator 的区别仅在于最外层的 `[]``()`
但是生成器并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生” ( yield ) 出来。
生成器表达式使用了“惰性计算” ( lazy evaluation也有翻译为“延迟求值”我以为这种按需调用 call by need 的方式翻译为惰性更好一些),只有在检索时才被赋值( evaluated ),所以在列表比较长的情况下使用内存上更有效。
那么竟然知道了如何创建一个生成器,那么怎么查看里面的元素呢?
@ -55,7 +65,11 @@ for num in gen :
上面也提到,创建生成器最简单最简单的方法就是把一个列表生成式的 `[]` 改成 `()`。为啥突然来个以函数的形式来创建呢?
其实生成器也是一种迭代器但是你只能对其迭代一次。这是因为它们并没有把所有的值存在内存中而是在运行时生成值。你通过遍历来使用它们要么用一个“for”循环要么将它们传递给任意可以进行迭代的函数和结构。而且实际运用中大多数的生成器都是通过函数来实现的。那么我们该如何通过函数来创建呢
其实生成器也是一种迭代器,但是你只能对其迭代一次。
这是因为它们并没有把所有的值存在内存中而是在运行时生成值。你通过遍历来使用它们要么用一个“for”循环要么将它们传递给任意可以进行迭代的函数和结构。
而且实际运用中,大多数的生成器都是通过函数来实现的。那么我们该如何通过函数来创建呢?
先不急,来看下这个例子:
@ -119,9 +133,9 @@ for x in fibon(1000000):
运行的效果:
![计算斐波那契数列的生成器](http://upload-images.jianshu.io/upload_images/2136918-304e50af22b787ce?imageMogr2/auto-orient/strip)
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-07-%E8%AE%A1%E7%AE%97%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97%E7%9A%84%E7%94%9F%E6%88%90%E5%99%A8.gif)
你看,运行一个这么的参数,也不会说有卡死的状态,因为这种方式不会使用太大的资源。这里,最难理解的就是 generator 和函数的执行流程不一样。函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成 generator 的函数,在每次调用 next() 的时候执行,遇到 yield语句返回再次执行时从上次返回的 yield 语句处继续执行。
你看,运行一个这么的参数,也不会说有卡死的状态,因为这种方式不会使用太大的资源。这里,最难理解的就是 generator 和函数的执行流程不一样。函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成 generator 的函数,在每次调用 next() 的时候执行,遇到 yield语句返回再次执行时从上次返回的 yield 语句处继续执行。
比如这个例子:
@ -189,3 +203,5 @@ for t in triangles( 10 ): # 直接修改函数名即可运行
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
```

View File

@ -0,0 +1,11 @@
# 前言 #
这篇内容挺多的,而且比内容不好理解。或许新手看完后,还会一脸懵逼,不过这是正常的,如果你看完后,是迷糊的,那么建议你继续学习后面的内容,等学完,再回来看几次。
注:这也是我第二次修改内容没有改过的章节。
# 目录 #
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-07-%E8%BF%AD%E4%BB%A3%E5%99%A8%E5%92%8C%E7%94%9F%E6%88%90%E5%99%A8.png)

View File

@ -1,11 +1,23 @@
# 一、面向对象的概念 #
Python 是一门面向对象的语言, 面向对象是一种抽象,抽象是指用分类的眼光去看世界的一种方法。 用 JAVA 的编程思想来说就是:万事万物皆对象。也就是说在面向对象中,把构成问题事务分解成各个对象。
面向对象有三大特性,封装、继承和多态。
## 1、面向对象的两个基本概念 ##
编程语言中,一般有两种编程思维,面向过程和面向对象。
面向过程,看重的是解决问题的过程。
这好比我们解决日常生活问题差不多,分析解决问题的步骤,然后一步一步的解决。
而面向对象是一种抽象,抽象是指用分类的眼光去看世界的一种方法。
Python 就是一门面向对象的语言,
如果你学过 Java ,就知道 Java 的编程思想就是万事万物皆对象。Python 也不例外,在解决实际问题的过程中,可以把构成问题事务分解成各个对象。
面向对象都有两个基本的概率,分别是类和对象。
* **类**
用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
@ -15,8 +27,13 @@ Python 是一门面向对象的语言, 面向对象是一种抽象,抽象是
通过类定义的数据结构实例
## 2、面向对象的三大特性 ##
面向对象的编程语言,也有三大特性,继承,多态和封装性。
* **继承**
即一个派生类derived class继承基类base class的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
@ -30,3 +47,8 @@ Python 是一门面向对象的语言, 面向对象是一种抽象,抽象是
* **封装性**
“封装”就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体(即类);封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员。
**如果你是初次接触面向对象的编程语言,看到这里还一脸懵逼,不要紧,这是正常的。下面我们会通过大量的例子逐步了解 Python 的面向对象的知识。**

View File

@ -0,0 +1,83 @@
# 二、类的定义和调用 #
## 1、怎么理解类 ##
类是什么?
个人认为理解类,最简单的方式就是:类是一个变量和函数的集合。
可以看下下面的这张图。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-034102.png)
这张图很好的诠释了类,就是把变量和函数包装在一起。
当然我们包装也不是毫无目的的包装,我们会把同性质的包装在一个类里,这样就方便我们重复使用。
所以学到现在,你会发现很多编程的设计,都是为了我们能偷懒,重复使用。
## 2、怎么定义类 ##
知道了类是什么样子的,我们接下来就要学习怎么去定义类了。
类定义语法格式如下:
```python
class ClassName():
<statement-1>
.
.
.
<statement-N>
```
可以看到,我们是用 `class` 语句来自定义一个类的,其实这就好比我们是用 `def` 语句来定义一个函数一样。
竟然说类是变量和方法的集合包,那么我们来创建一个类。
```python
class ClassA():
var1 = 100
var2 = 0.01
var3 = '两点水'
def fun1():
print('我是 fun1')
def fun2():
print('我是 fun1')
def fun3():
print('我是 fun1')
```
你看,上面我们就定义了一个类,类名叫做 `ClassA` , 类里面的变量我们称之为属性,那么就是这个类里面有 3 个属性,分别是 `var1` , `var2``var3` 。除此之外,类里面还有 3 个类方法 `fun1()` , `fun2()``fun3()`
## 3、怎么调用类属性和类方法 ##
我们定义了类之后,那么我们怎么调用类里面的属性和方法呢?
直接看下图:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-083155.png)
这里就不文字解释了(注:做图也不容易啊,只有写过技术文章才知道,这系列文章,多耗时)
好了,知道怎么调用之后,我们尝试一下:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-085918.png)

View File

@ -0,0 +1,57 @@
# 三、类方法 #
## 1、类方法如何调用类属性 ##
通过上面我们已经会定义类了,那么这里讲一下在同一个类里,类方法如何调用类属性的。
直接看个例子吧:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-110451.png)
注意看,在类方法上面多了个 `@classmethod` ,这是干嘛用的呢?
这是用于声明下面的函数是类函数。其实从名字就很好理解了。
class 就是类method 就是方法。
那是不是一定需要注明这个呢?
答案是是的。
如果你没使用,是会报错的。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-110822.png)
如果没有声明是类方法,方法参数中就没有 `cls` , 就没法通过 `cls` 获取到类属性。
因此类方法,想要调用类属性,需要以下步骤:
* 在方法上面,用 `@classmethon` 声明该方法是类方法。只有声明了是类方法,才能使用类属性
* 类方法想要使用类属性,在第一个参数中,需要写上 `cls` , cls 是 class 的缩写,其实意思就是把这个类作为参数,传给自己,这样就可以使用类属性了。
* 类属性的使用方式就是 `cls.变量名`
记住喔,无论是 `@classmethon` 还是 `cls` ,都是不能省去的。
省了都会报错。
## 2、类方法传参 ##
上面我们学习了类方法如何调用类属性,那么类方法如何传参呢?
其实很简单,跟普通的函数一样,直接增加参数就好了。
这个就直接上例子了:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-113458.png)

View File

@ -0,0 +1,32 @@
# 四、修改和增加类属性 #
## 1、从内部增加和修改类属性 ##
来,我们先来温习一下类的结构。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-034102.png)
看着这个结构,提一个问题,如何修改类属性,也就是类里面的变量?
从类结构来看,我们可以猜测,从类方法来修改,也就是从类内部来修改和增加类属性。
看下具体的实例:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-120146.png)
这里还是强调一下,例子还是要自己多写,不要只看,自己运行, 看效果。多想。
## 2、从外部增加和修改类属性 ##
我们刚刚看了通过类方法来修改类的属性,这时我们看下从外部如何修改和增加类属性。
例子如下:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-121135.png)

View File

@ -0,0 +1,171 @@
# 五、类和对象 #
## 1、类和对象之间的关系 ##
这部分内容主要讲类和对象,我们先来说说类和对象之间的关系。
**类是对象的模板**
我们得先有了类,才能制作出对象。
类就相对于工厂里面的模具,对象就是根据模具制造出来的产品。
**从模具变成产品的过程,我们就称为类的实例化。**
**类实例化之后,就变成对象了。也就是相当于例子中的产品。**
## 2、类的实例化 ##
这里强调一下,类的实例化和直接使用类的格式是不一样的。
之前我们就学过,直接使用类格式是这样的:
```python
class ClassA():
var1 = '两点水'
@classmethod
def fun1(cls):
print('var1 值为:' + cls.var1)
ClassA.fun1()
```
而类的实例化是怎样的呢?
是这样的,可以仔细对比一下,类的实例化和直接使用类的格式有什么不同?
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-025401.png)
主要的不同点有:
* 类方法里面没有了 `@classmethod` 声明了,不用声明他是类方法
* 类方法里面的参数 `cls` 改为 `self`
* 类的使用,变成了先通过 `实例名 = 类()` 的方式实例化对象,为类创建一个实例,然后再使用 `实例名.函数()` 的方式调用对应的方法 ,使用 `实例名.变量名` 的方法调用类的属性
这里说明一下,类方法的参数为什么 `cls` 改为 `self`
其实这并不是说一定要写这个,你改为什么字母,什么名字都可以。
不妨试一下:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-032030.png)
你看,把 `self` 改为 `aaaaaaaa` 还是可以一样运行的。
只不过使用 `cls``self` 是我们的编程习惯,这也是我们的编程规范。
因为 cls 是 class 的缩写,代表这类 而 self 代表这对象的意思。
所以啊,这里我们实例化对象的时候,就使用 self 。
**而且 self 是所有类方法位于首位、默认的特殊参数。**
除此之外,在这里,还要强调一个概念,当你把类实例化之后,里面的属性和方法,就不叫类属性和类方法了,改为叫实例属性和实例方法,也可以叫对象属性和对象方法。
为什么要这样强调呢?
**因为一个类是可以创造出多个实例对象出来的。**
你看下面的例子:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-034453.png)
我不仅能用这个类创建 a 对象,还能创建 b 对象
## 3、实例属性和类属性 ##
一个类可以实例化多个对象出来。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-040408.png)
根据这个图,我们探究一下实例对象的属性和类属性之间有什么关系呢?
**先提出第一个问题,如果类属性改变了,实例属性会不会跟着改变呢?**
还是跟以前一样,提出了问题,我们直接用程序来验证就好。
看程序:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-061015.png)
从程序运行的结果来看,**类属性改变了,实例属性会跟着改变。**
这很好理解,因为我们的实例对象就是根据类来复制出来的,类属性改变了,实例对象的属性也会跟着改变。
**那么相反,如果实例属性改变了,类属性会改变吗?**
答案当然是不能啦。因为每个实例都是单独的个体,不能影响到类的。
具体我们做下实验:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-062437.png)
可以看到,**不管实例对象怎么修改属性值,对类的属性还是没有影响的。**
## 4、实例方法和类方法 ##
那这里跟上面一样,还是提出同样的问题。
**如果类方法改变了,实例方法会不会跟着改变呢?**
看下下面的例子:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-063242.png)
这里建议我的例子,各位都要仔细看一下,自己重新敲一遍。相信为什么要这么做,这么证明。
还是那句话多想,多敲。
回归正题,从运行的结果来看,类方法改变了,实例方法也是会跟着改变的。
在这个例子中,我们需要改变类方法,就用到了**类的重写**。
我们使用了 `类.原始函数 = 新函数` 就完了类的重写了。
要注意的是,这里的赋值是在替换方法,并不是调用函数。所以是不能加上括号的,也就是 `类.原始函数() = 新函数()` 这个写法是不对的。
**那么如果实例方法改变了,类方法会改变吗?**
如果这个问题我们需要验证的话,是不是要重写实例的方法,然后观察结果,看看类方法有没有改变,这样就能得出结果了。
可是我们是不能重写实例方法。
你看,会直接报错。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-064303.png)

View File

@ -0,0 +1,146 @@
# 六、初始化函数 #
## 1、什么是初始化函数 ##
初始化函数的意思是,当你创建一个实例的时候,这个函数就会被调用。
比如:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-071102.png)
当代码在执行 `a = ClassA()` 的语句时,就自动调用了 `__init__(self)` 函数。
**而这个 `__init__(self)` 函数就是初始化函数,也叫构造函数。**
初始化函数的写法是固定的格式:中间是 `init`,意思是初始化,然后前后都要有【两个下划线】,然后 `__init__()` 的括号中,第一个参数一定要写上 `self`,不然会报错。
构造函数(初始化函数)格式如下:
```python
def __init__(self,[...):
```
初始化函数一样可以传递参数的,例如:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-073421.png)
## 2、析构函数 ##
竟然一个在创建的时候,会调用构造函数,那么理所当然,这个当一个类销毁的时候,就会调用析构函数。
析构函数语法如下:
```python
def __del__(self,[...):
```
看下具体的示例:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-084417.png)
## 3、Python 定义类的历史遗留问题 ##
Python 在版本的迭代中,有一个关于类的历史遗留问题,就是新式类和旧式类的问题,具体先看以下的代码:
```python
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# 旧式类
class OldClass:
pass
# 新式类
class NewClass(object):
pass
```
可以看到,这里使用了两者中不同的方式定义类,可以看到最大的不同就是,新式类继承了`object` 类,在 Python2 中,我们定义类的时候最好定义新式类,当然在 Python3 中不存在这个问题了,因为 Python3 中所有类都是新式类。
那么新式类和旧式类有什么区别呢?
运行下下面的那段代码:
```python
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# 旧式类
class OldClass:
def __init__(self, account, name):
self.account = account
self.name = name
# 新式类
class NewClass(object):
def __init__(self, account, name):
self.account = account
self.name = name
if __name__ == '__main__':
old_class = OldClass(111111, 'OldClass')
print(old_class)
print(type(old_class))
print(dir(old_class))
print('\n')
new_class = NewClass(222222, 'NewClass')
print(new_class)
print(type(new_class))
print(dir(new_class))
```
这是 python 2.7 运行的结果:
```
/Users/twowater/dev/python/test/venv/bin/python /Users/twowater/dev/python/test/com/twowater/test.py
<__main__.OldClass instance at 0x109a50560>
<type 'instance'>
['__doc__', '__init__', '__module__', 'account', 'name']
<__main__.NewClass object at 0x109a4b150>
<class '__main__.NewClass'>
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'account', 'name']
Process finished with exit code 0
```
这是 Python 3.6 运行的结果:
```
/usr/local/bin/python3.6 /Users/twowater/dev/python/test/com/twowater/test.py
<__main__.OldClass object at 0x1038ba630>
<class '__main__.OldClass'>
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'account', 'name']
<__main__.NewClass object at 0x103e3c9e8>
<class '__main__.NewClass'>
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'account', 'name']
Process finished with exit code 0
```
仔细观察输出的结果对比一下就能观察出来注意喔Pyhton3 中输出的结果是一模一样的因为Python3 中没有新式类旧式类的问题。

View File

@ -1,7 +1,16 @@
# 、类的继承 #
# 、类的继承 #
## 1、定义类的继承 ##
说到继承,你一定会联想到继承你老爸的家产之类的。
类的继承也是一样。
比如有一个旧类,是可以算平均数的。然后这时候有一个新类,也要用到算平均数,那么这时候我们就可以使用继承的方式。新类继承旧类,这样子新类也就有这个功能了。
通常情况下,我们叫旧类为父类,新类为子类。
首先我们来看下类的继承的基本语法:
```python
@ -13,7 +22,7 @@ class ClassName(BaseClassName):
<statement-N>
```
在定义类的时候,可以在括号里写继承的类,一开始也提到过,如果不用继承类的时候,也要写继承 object 类,因为在 Python 中 object 类是一切类的父类。
在定义类的时候,可以在括号里写继承的类,如果不用继承类的时候,也要写继承 object 类,因为在 Python 中 object 类是一切类的父类。
当然上面的是单继承Python 也是支持多继承的,具体的语法如下:
@ -112,12 +121,12 @@ if __name__ == '__main__':
最后打印的结果:
![Python 类的继承](http://upload-images.jianshu.io/upload_images/2136918-aa2701fc5913a8a6?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-Python%20%E7%B1%BB%E7%9A%84%E7%BB%A7%E6%89%BF.png)
这里就是重写了父类的构造函数。
## 3、子类的类型判断 ##
## 4、子类的类型判断 ##
对于 class 的继承关系来说,有些时候我们需要判断 class 的类型,该怎么办呢?
@ -168,3 +177,5 @@ False
```
可以看到 `isinstance()` 不仅可以告诉我们,一个对象是否是某种类型,也可以用于基本类型的判断。

View File

@ -1,4 +1,4 @@
# 、类的多态 #
# 、类的多态 #
多态的概念其实不难理解,它是指对不同类型的变量进行相同的操作,它会根据对象(或类)类型的不同而表现出不同的行为。
@ -11,7 +11,9 @@
'ab'
```
可以看到,我们对两个整数进行 + 操作,会返回它们的和,对两个字符进行相同的 + 操作,会返回拼接后的字符串。也就是说,不同类型的对象对同一消息会作出不同的响应。
可以看到,我们对两个整数进行 + 操作,会返回它们的和,对两个字符进行相同的 + 操作,会返回拼接后的字符串。
也就是说,不同类型的对象对同一消息会作出不同的响应。
看下面的实例,来了解多态:
@ -64,4 +66,5 @@ Hello ! 尊敬的用户:水水水
最后,本章的所有代码都可以在 [https://github.com/TwoWater/Python](https://github.com/TwoWater/Python) 上面找到,文章的内容和源文件都放在上面。同步更新到 Gitbooks。
最后,本章的所有代码都可以在 [https://github.com/TwoWater/Python](https://github.com/TwoWater/Python) 上面找到,文章的内容和源文件都放在上面。同步更新到 Gitbooks。

View File

@ -1,6 +1,62 @@
# 四、类的方法 #
# 九、类的访问控制 #
## 1、类专有的方法 ##
## 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、类专有的方法 ##
一个类创建的时候,就会包含一些方法,主要有以下方法:
@ -32,7 +88,9 @@
* `setattr(obj, attr, value)`:设定该属性/方法的值,类似于 obj.attr=value
* `dir(obj)`:可以获取相应对象的所有属性和方法名的列表:
## 2、方法的访问控制 ##
## 3、方法的访问控制 ##
其实我们也可以把方法看成是类的属性的,那么方法的访问控制也是跟属性是一样的,也是没有实质上的私有方法。一切都是靠程序员自觉遵守 Python 的编程规范。
@ -54,53 +112,7 @@ class User(object):
```
## 3、方法的装饰器 ##
* **@classmethod**
调用的时候直接使用类名类调用,而不是某个对象
* **@property**
可以像访问属性一样调用方法
具体的使用看下实例:
```python
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
class UserInfo(object):
lv = 5
def __init__(self, name, age, account):
self.name = name
self._age = age
self.__account = account
def get_account(self):
return self.__account
@classmethod
def get_name(cls):
return cls.lv
@property
def get_age(self):
return self._age
if __name__ == '__main__':
userInfo = UserInfo('两点水', 23, 347073565);
# 打印所有属性
print(dir(userInfo))
# 打印构造函数中的属性
print(userInfo.__dict__)
# 直接使用类名类调用,而不是某个对象
print(UserInfo.lv)
# 像访问属性一样调用方法注意看get_age是没有括号的
print(userInfo.get_age)
```
运行的结果:
![Python 方法的装饰器](http://upload-images.jianshu.io/upload_images/2136918-63dc478a8b2f965f?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

View File

@ -0,0 +1,26 @@
# 前言 #
这篇内容非常的重要,也是我用了很多时间写的。基本上把以前写的东西都重新改了一遍。里面的代码都是我一个一个的敲的,图片也是我一个一个制作的。
# 目录 #
![面向对象](media/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@ -1,42 +0,0 @@
# 一、Python 自定义函数的基本步骤 #
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
自定义函数,基本有以下规则步骤:
* 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()
* 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数
* 函数的第一行语句可以选择性地使用文档字符串(用于存放函数说明)
* 函数内容以冒号起始,并且缩进
* return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的 return 相当于返回 None。
语法示例:
```python
def functionname( parameters ):
"函数_文档字符串"
function_suite
return [expression]
```
实例:
1. def 定义一个函数,给定一个函数名 sum
2. 声明两个参数 num1 和 num2
3. 函数的第一行语句进行函数说明:两数之和
4. 最终 return 语句结束函数,并返回两数之和
```python
def sum(num1,num2):
"两数之和"
return num1+num2
# 调用函数
print(sum(5,6))
```
输出结果:
```python
11
```

View File

@ -1,7 +0,0 @@
# 前言 #
前天创了个 Python 微信讨论群,以为没人进的,哈哈,想不到还真有小伙伴进群学习讨论。如果想进群,可以加我微信: androidwed ,拉进群,就不贴微信群二维码了,一是会失效,二影响文章。
# 目录 #
![草根学Python 函数](http://upload-images.jianshu.io/upload_images/2136918-be9226fe109027f3?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

View File

@ -1,7 +0,0 @@
# 前言 #
这篇博客写了很久其实写每一篇博客用的时间还是挺长的不够这有利于自己的学习也想分享一下。之前也说了创建了一个微信群Python 学习讨论群,现在只有 40 个左右的小伙伴,如果有兴趣加入学习讨论的话,可以加我微信:`androidwed`,拉你进群。想看回之前的文章,也可以通过 [Gitbook](https://www.gitbook.com/book/twowater/python/details) 查看,欢迎提出问题和点下 star及时查看更新。
# 目录 #
![草根学Python 迭代器和生成器](http://upload-images.jianshu.io/upload_images/2136918-b350c0e98ca47183?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

View File

@ -1,117 +0,0 @@
# 二、类 #
## 1、定义类 ##
类定义语法格式如下:
```python
class ClassName:
<statement-1>
.
.
.
<statement-N>
```
一个类也是由属性和方法组成的,有些时候我们定义类的时候需要设置类的属性,因此这就需要构造函
类的构造函数如下:
```python
def __init__(self,[...):
```
类定义了 __init__() 方法的话,类的实例化操作会自动调用 __init__() 方法。
那么如构造函数相对应的是析构函数,理所当然,一个类创建的时候我们可以用过构造函数设置属性,那么当一个类销毁的时候,就会调用析构函数。
析构函数语法如下:
```python
def __del__(self,[...):
```
仔细观察的童鞋都会发现,类的方法与普通的函数有一个特别的区别,它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
那么这个 self 代表什么呢?
我们可以看下实例,通过实例来找出答案:
```python
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
```
观察输出的结果:
![Python self](http://upload-images.jianshu.io/upload_images/2136918-66d29b081ad5510b?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
从执行结果可以很明显的看出self 代表的是类的实例,输出的是当前对象的地址,而 `self.__class__` 则指向类。
当然 self 不是 python 关键字,也就是说我们把他换成其他的字符也是可以正常执行的。只不过我们习惯使用 self
## 2、Python 定义类的历史遗留问题 ##
Python 在版本的迭代中,有一个关于类的历史遗留问题,就是新式类和旧式类的问题,具体先看以下的代码:
```python
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# 旧式类
class OldClass:
pass
# 新式类
class NewClass(object):
pass
```
可以看到,这里使用了两者中不同的方式定义类,可以看到最大的不同就是,新式类继承了`object` 类,在 Python2 中,我们定义类的时候最好定义新式类,当然在 Python3 中不存在这个问题了,因为 Python3 中所有类都是新式类。
那么新式类和旧式类有什么区别呢?
运行下下面的那段代码:
```python
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# 旧式类
class OldClass:
def __init__(self, account, name):
self.account = account;
self.name = name;
# 新式类
class NewClass(object):
def __init__(self, account, name):
self.account = account;
self.name = name;
if __name__ == '__main__':
old_class = OldClass(111111, 'OldClass')
print(old_class)
print(type(old_class))
print(dir(old_class))
print('\n')
new_class=NewClass(222222,'NewClass')
print(new_class)
print(type(new_class))
print(dir(new_class))
```
仔细观察输出的结果对比一下就能观察出来注意喔Pyhton3 中输出的结果是一模一样的因为Python3 中没有新式类旧式类的问题。

View File

@ -1,64 +0,0 @@
# 三、类的属性 #
## 1、直接在类中定义属性 ##
定义类的属性,当然最简单最直接的就是在类中定义,例如:
```python
class UserInfo(object):
name='两点水'
```
## 2、在构造函数中定义属性 ##
故名思议,就是在构造对象的时候,对属性进行定义。
```python
class UserInfo(object):
def __init__(self,name):
self.name=name
```
## 3、属性的访问控制 ##
在 Java 中,有 public (公共)属性 和 private (私有)属性,这可以对属性进行访问控制。那么在 Python 中有没有属性的访问控制呢?
一般情况下,我们会使用 `__private_attrs` 两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时 `self.__private_attrs`
为什么只能说一般情况下呢?因为实际上, Python 中是没有提供私有属性等功能的。但是 Python 对属性的访问控制是靠程序员自觉的。为什么这么说呢?看看下面的示例:
![Python 属性访问控制](http://upload-images.jianshu.io/upload_images/2136918-4ac2643aa5b0fa37?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
仔细看图片,为什么说双下划线不是真正的私有属性呢?我们看下下面的例子,用下面的例子来验证:
```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)
```
输出的结果如下图:
![Python 属性访问控制](http://upload-images.jianshu.io/upload_images/2136918-de89d4dc5f5f9f77?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

View File

@ -1,10 +0,0 @@
# 前言 #
这篇写的很纠结,不过还是写完了。弄了个很逊的公众号,如果对本文有兴趣,可以关注下公众号喔,会持续更新。
![公众号](http://img.blog.csdn.net/20170730171715934?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvVHdvX1dhdGVy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
# 目录 #
![草根学Python面向对象](http://upload-images.jianshu.io/upload_images/2136918-eecf427fdbd1688c?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

View File

@ -4,6 +4,7 @@ IT 行业相对于一般传统行业,发展更新速度更快,一旦停止
自学 Python ,也是一样,不要一开始因为头脑发热就不停地收藏各种资料网站,购买各种书籍,下载了大量的教学视频,过了几天,学习的热情开始褪去,再过几个星期,终于完成了学习课程 —— 《从入门到放弃》。所以,学习 Python 需要一步一个脚印,踏踏实实地学。
# FQ
在讲 Python 如何入门之前,个人建议最好每个人都有自己的 FQ 工具,多使用 Google 搜索,多去看一下墙外的世界,多看 Github 上的开源项目。
@ -11,6 +12,7 @@ IT 行业相对于一般传统行业,发展更新速度更快,一旦停止
至于如何 FQ ,这里提供一下我用过的工具:[FQ工具集](/Res/FQ.md)
# Python 学习资源集
相信很多人学习某门编程语言的时候,都会找各种学习资料。说句实话,资料太多,反而没用,根据自己的学习习惯,个人能力选择一门资源坚持学就好了。
@ -19,6 +21,11 @@ IT 行业相对于一般传统行业,发展更新速度更快,一旦停止
* [Python 博客网站资源](/Res/Python博客网站资源.md)
还有一些有趣的网站:
* [一个可以看执行过程的网站](http://www.pythontutor.com/visualize.html#mode=edit)
# Python 入门
@ -57,31 +64,34 @@ IT 行业相对于一般传统行业,发展更新速度更快,一旦停止
- [条件语句](/Article/PythonBasis/python5/If.md)
- [循环语句](/Article/PythonBasis/python5/Cycle.md)
- [条件语句和循环语句综合实例](/Article/PythonBasis/python5/Example.md)
* [函数](/Article/python6/Preface.md)
- [Python 自定义函数的基本步骤](/Article/python6/1.md)
- [函数传值问题](/Article/python6/2.md)
- [函数返回值](/Article/python6/3.md)
- [函数的参数](/Article/python6/4.md)
- [匿名函数](/Article/python6/5.md)
* [迭代器和生成器](/Article/python7/Preface.md)
- [迭代](/Article/python7/1.md)
- [Python 迭代器](/Article/python7/2.md)
- [lsit 生成式(列表生成式)](/Article/python7/3.md)
- [生成器](/Article/python7/4.md)
- [迭代器和生成器综合例子](/Article/python7/5.md)
* [模块与包](/Article/python8/Preface.md)
- [Python 模块简介](/Article/python8/1.md)
- [模块的使用](/Article/python8/2.md)
- [主模块和非主模块](/Article/python8/3.md)
- [](/Article/python8/4.md)
- [作用域](/Article/python8/5.md)
* [面向对象](/Article/python9/Preface.md)
- [面向对象的概念](/Article/python9/1.md)
- [](/Article/python9/2.md)
- [类的属性](/Article/python9/3.md)
- [类的方法](/Article/python9/4.md)
- [类的继承](/Article/python9/5.md)
- [类的多态](/Article/python9/6.md)
* [函数](/Article/PythonBasis/python6/Preface.md)
- [Python 自定义函数的基本步骤](/Article/PythonBasis/python6/1.md)
- [函数返回值](/Article/PythonBasis/python6/2.md)
- [函数的参数](/Article/PythonBasis/python6/3.md)
- [函数传值问题](/Article/PythonBasis/python6/4.md)
- [匿名函数](/Article/PythonBasis/python6/5.md)
* [迭代器和生成器](/Article/PythonBasis/python7/Preface.md)
- [迭代](/Article/PythonBasis/python7/1.md)
- [Python 迭代器](/Article/PythonBasis/python7/2.md)
- [lsit 生成式(列表生成式)](/Article/PythonBasis/python7/3.md)
- [生成器](/Article/PythonBasis/python7/4.md)
- [迭代器和生成器综合例子](/Article/PythonBasis/python7/5.md)
* [面向对象](/Article/PythonBasis/python8/Preface.md)
- [面向对象的概念](/Article/PythonBasis/python8/1.md)
- [类的定义和调用](/Article/PythonBasis/python8/2.md)
- [类方法](/Article/PythonBasis/python8/3.md)
- [修改和增加类属性](/Article/PythonBasis/python8/4.md)
- [类和对象](/Article/PythonBasis/python8/5.md)
- [初始化函数](/Article/PythonBasis/python8/6.md)
- [类的继承](/Article/PythonBasis/python8/7.md)
- [类的多态](/Article/PythonBasis/python8/8.md)
- [类的访问控制](/Article/PythonBasis/python8/9.md)
* [模块与包](/Article/PythonBasis/python9/Preface.md)
- [Python 模块简介](/Article/PythonBasis/python9/1.md)
- [模块的使用](/Article/PythonBasis/python9/2.md)
- [主模块和非主模块](/Article/PythonBasis/python9/3.md)
- [](/Article/PythonBasis/python9/4.md)
- [作用域](/Article/PythonBasis/python9/5.md)
* [Python 的 Magic Method](/Article/python10/Preface.md)
- [Python 的 Magic Method](/Article/python10/1.md)
- [构造(`__new__`)和初始化(`__init__`)](/Article/python10/2.md)
@ -115,10 +125,12 @@ IT 行业相对于一般传统行业,发展更新速度更快,一旦停止
* [装饰器](/Article/python16/1.md)
# 知识点补漏
* [Python 关键字 yield](/Article/supplement/Python关键字yield.md)
# Python 进阶
* [使用Python虚拟环境](/Article/advanced/使用Python虚拟环境.md)