Python速成

快速上手Python,为后续学习做好前置准备。

教程链接:Datawhale-聪明方法学Python

本文章只记录作者认为的重难点,详细学习教程还请直接点击上方链接查看。
此时作者已有C基础。

原教程是ipynb格式,可以在Jupyter Notebook上运行,直接跟着引导运行代码块就可以。

注意:以下内容看完并不能掌握,必须加以练习,况且下面知识点并不全面。

补充提示:辅助教程链接:Python小白逆袭大神

常量

Python 中的常量包括数字,字符串,逻辑值三种。

  • 数字:整数(例如2),浮点数(例如2.333 或 1e-9 = )
  • 字符串:用单/双/三引号括起来的内容,例如('Hi' 或 "Hi" 或 '''Hi''')
  • 逻辑值(@C艹、Java里的bool类型):True 代表真, False 代表假
    type(*)可以查看 * 的类型,例如 type(2) 返回 int 表示 2 为 整数。

运算符

运算符有以下几种,表示运算操作/逻辑操作/位运算操作
剔除直觉正确的运算符号。

  • 算数运算符:

    • * 表示乘法,1 * 2 的结果是 2
    • ** 表示乘方,1 ** 2 的结果是 1
    • / 表示除法,1 / 2 的结果是 0.5 (注意,与C不同,现在默认是Python3,该版本中/就是精确除法)
    • // 表示整除,1 // 2 的结果是 0 (相当于除法结果向下取整,也相当于C中的除法),此外别忘了,C/C++/Java中的 // 是注释
    • % 表示取余 1 % 2 的结果是 1
  • 逻辑运算符

    • 大于小于号的用法与C无异
    • and 表示逻辑"与",True and False 的结果是 False
    • or 表示逻辑"或",True or False 的结果是 True
    • not 表示逻辑"非",not True 的结果是 False
  • 位运算符

    • >> 表示右移操作
    • << 表示左移操作
    • & 表示按位与
    • | 表示按位或
    • ^ 表示按位亦或
    • ~ 表示按位取反

其中最常用的是算数运算符与逻辑运算符,位运算符在 集合 操作中经常使用。

函数

函数通过 def 关键字定义,函数的输入由函数名后括号内 参数 定义,函数的结果由 return 关键字定义。

函数的 参数 由逗号分隔,在定义函数时的参数叫做形参,在使用函数时输入的参数叫做实参。
函数的 返回值 是函数的返回结果,参数与返回值都是可选的。

1
2
3
4
5
6
7
8
9
## num1,num2 是输入的参数, return 后面的 a+b==target 是函数的结果

## 这里num1,num2,target 是形参
def check_sum(num1, num2, target):
## 在 def xxx(): 下面缩进的是函数的内容
a = num1
b = num2
return a + b == target #返回a+b与target判断是否相等的结果(bool)
#Python中没有 “//” 作为注释了哈

python缩进敏感,所以不需要像C++中用花括号框出代码块。

1
print(check_sum(2,3,13))

输出:False

前面函数定义中的几个变量是局部变量,使用全局变量时,使用global标注。

控制流

while

1
2
3
4
a = 0
while a < 5:
a = a + 1
print(a)

结果:

1

2

3

4

5

for-in

1
2
for i in [1,2,3,4,5]:
print(i)

结果:

1

2

3

4

5

注意 [**]里面括起来的是序列,for-in根据某一序列进行循环,直至循环结束

if-else

if,else的思路与C相同,pass表示不进行任何操作,多个同级if用elif。

1
2
3
4
5
6
7
8
9
10
11
12
age = int( input("请输入你的年龄:") )

if age < 12 :
print("婴幼儿")
elif age >= 12 and age < 18:
print("青少年")
elif age >= 18 and age < 30:
print("成年人")
elif age >= 30 and age < 50:
pass #不进行任何操作
else:
print("老年人")

break&continue

与C/C++/Java比较类似

数据结构

Python常用数据结构

  • 序列 List: 用于保存有序项集合的变量,以方括号标识。[]
  • 元组 Tuple: 用于保存有序项集合的常量,以圆括号标识。()
  • 字典 Dict: 用于保存无序(键,值)项集合的变量,以花括号标识。{}
  • 集合 Set: 用于保存无序项集合的变量,以花括号标识。{}

序列

1
l = [1,2,3,4]

序列支持以下操作:

  • 增:通过函数 append 可以向序列内增加元素
  • 删:通过关键字 del 可以删除序列内元素
  • 查:通过关键字 [ ] 可以查找序列某个位置元素
  • 改:通过赋值符号 = 可以修改某个位置的元素

序列的优点是:

  • 快速向尾部添加元素
  • 快速遍历所有元素
  • 节省占用计算机内容空间
1
2
3
4
5
6
7
8
## 查找 首个 元素
print(l[0])
## 查找第 2 个元素
print(l[2])
## 查找第 最后 元素
print(l[-1])
## 查找倒数第 2 个元素
print(l[-2])

1

2

3

4

[ ]可以切片,获得一段序列

1
2
3
4
## 查找第 0 到 第 2 的元素子序列
print(l[0:2])
## 查找第 1 到 最后 的元素子序列
print(l[1:-1])

[1, 2]
[2, 3]

1
2
3
## 修改 首个 元素的值为 -1
l[0] = -1
print(l)

[-1,2,3,4]

1
2
3
## 修改从第 0 到第 2 的元素子序列的值为 [-1, -2]
l[0:2] = [-1, -2]
print(l)

[-1, -2, 3, 4]

1
2
3
4
5
6
## 向集合尾部添加元素 5
l.append(5)
print(l)
## 向集合尾部添加元素 6
l.append(6)
print(l)

结果:

[-1, -2, 3, 4, 5]
[-1, -2, 3, 4, 5, 6]

1
2
3
4
5
6
## 删除序列 首个 元素
del l[0]
print(l)
## 删除序列 最后一个 元素
del l[-1] #最后一个元素 -1,倒数第二-2,以此类推
print(l)

[-2, 3, 4, 5, 6]
[-2, 3, 4, 5]

元组

可以理解为常量序列,即,无法修改

1
2
3
4
t = (1,2,3,4)

#尝试修改
t[0] = -1

报错无法修改,增删改都不支持,只能查询

字典

“键(key)” 与 “值(value)” 的关联

1
2
3
4
5
ab = {
"XiaoHu": "xiaohu@RNG.com",
"XiaoWei": "xiaowei@RNG.com",
"XiaoMing": "xiaoming@RNG.com"
}
1
print(ab)

{‘XiaoHu’: ‘xiaohu@RNG.com’, ‘XiaoWei’: ‘xiaowei@RNG.com’, ‘XiaoMing’: ‘xiaoming@RNG.com’}

同样支持序列的增删改查动作,注意在定义时用(),增查的时候用[]。

1
2
3
4
## 通过 [ ] 关键字 与赋值符号 = 向字典添加新的元素

ab['Cryin'] = "cryin@RNG.com"
print(ab)

{‘XiaoHu’: ‘xiaohu@RNG.com’, ‘XiaoWei’: ‘xiaowei@RNG.com’, ‘XiaoMing’: ‘xiaoming@RNG.com’, ‘Cryin’: ‘cryin@RNG.com’}

1
2
3
4
## 通过 del 关键字 删除字典中的元素

del ab['XiaoMing']
print(ab)

{‘XiaoHu’: ‘xiaohu@RNG.com’, ‘XiaoWei’: ‘xiaowei@RNG.com’, ‘Cryin’: ‘cryin@RNG.com’}

1
2
3
## 通过 [ ] 关键字根据键查找值

print(ab['XiaoHu'])

xiaohu@RNG.com

1
2
3
## 通过 in 关键字可以查找某个键是否在字典中
print('XiaoHu' in ab)
print('UZI' in ab)

True

False

集合

存储无序的元素集合。只考虑元素的存在,不考虑元素的顺序或出现次数时使用集合

集合与字典一样也通过花括号创建,但不存在 : 分隔符号。例如用集合表示中国的四个直辖市,它们无需考虑顺序与出现次数。

注意 集合中不能存在重复元素

集合支持以下操作:

  • 增:通过函数 add 可以向集合内增加元素
  • 删:通过函数 remove 可以删除集合内元素
  • 查:通过关键字 in 可以查找某个元素是否在集合内

集合的优点是:

  • 支持数学集合操作
  • 快速检索某个元素是否在集合内
  • 集合内的键值不存在顺序关系
集合基本操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
## 创建一个集合
s = {1,2,3,4,5}

## 增加新的元素到集合中
s.add(6)
print(s)
#{1, 2, 3, 4, 5, 6}

## 删除集合中某个元素
s.remove(6)
print(s)
#{1, 2, 3, 4, 5}

## 查找某个元素是否在集合中
print(5 in s)
print(6 in s)
#True
#False
数学操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
## 创建另一个集合
s2 = {3,4,5,6,7}

## 集合并集
print(s | s2)
#{1, 2, 3, 4, 5, 6, 7}

## 集合交集
print(s & s2)
#{3, 4, 5}

## 集合亦或
print(s ^ s2)
#{1, 2, 6, 7}

面向对象

Python语言具有面向对象的特性呢,Java/C++也是。C是面向过程,但是可以联想结构题,共同体,然后来理解一下不同之处。

类与对象

1
2
3
##创建一个student类
class student():
pass

看起来像函数一样,只是定义关键字是class

使用类的名字和一对括号可以创建类的对象:

1
2
3
4
5
6
## 使用 类的名字 student 与 括号() 可以创建类的对象 xiaohu
xiaohu = student()
xiaoming = student()

print(type(xiaohu))
print(type(xiaoming))

<class ‘main.student’>
<class ‘main.student’>

类与对象中的变量

在 Python 中类的变量用于表示类的属性。student 表示学生类,在我们的系统中我们只关注学生的姓名、数学成绩和语文成绩而不考虑其他,分别用类变量 name, math_score, language_score 表示。这体现了面向对象编程的”抽象性“。

1
2
3
4
5
6
## 创建一个 student 类
class student():
## 类的内部定义三个内部变量,并定义他们的初始值
name = 'Undifined'
math_score = -1
language_score = -1

在 Python 中对象拥有与类相同的数据和操作,因此通过类创建的对象也拥有相同的变量。我们使用 . 符号来引用对象或类的变量与函数:

1
2
3
4
5
6
## 使用 类的名字 student 与 括号() 可以创建类的对象 xiaohu
xiaohu = student()
## 使用 . 符号引用对象xiaohu的变量name、math_score、language_score
print(xiaohu.name)
print(xiaohu.math_score)
print(xiaohu.language_score)

Undifined
-1
-1

然后使用赋值符号改变对象内数据:

1
2
3
4
5
6
7
8
## 通过赋值符号改变对象内变量的值
xiaohu.name = 'XiaoHu'
xiaohu.math_score = 65
xiaohu.language_score = 55

print(xiaohu.name)
print(xiaohu.math_score)
print(xiaohu.language_score)

XiaoHu

65

55

在这里我们要注意区分两个概念,类变量与对象变量,在上述代码中 student.name 是类变量,xiaohu.name 是对象变量。

  • 类变量属于类,更改类变量会影响所有后续由该类创建对象的属性。
  • 对象变量属于对象,更改对象变量只影响该对象的属性。

那修改类变量会产生什么结果呢?

1
2
3
4
5
6
7
8
9
10
## 更改类变量会影响所有后续由该类创建对象的属性。
xiaoming = student()
print(xiaoming.name)

## 修改 student.name 再次创建新对象 xiaoming
student.name = 'Change Name'
xiaoming = student()

## xiaoming.name 不再是 undefined 而是 change name
print(xiaoming.name)

Undifined
Change Name

类与对象中的函数

在 Python 中类函数用于表示类的操作,它又被称作为“方法”。它们与之前我们学到的函数类似,但是类函数必须有一个额外的 self 参数:

1
2
3
4
5
6
7
8
class student():
## 定义类函数时要有一个特殊的 self 参数
def print_name(self,):
print(self.name)

name = 'Undifined'
math_score = -1
language_score = -1
1
2
3
xiaohu = student()
xiaohu.name = 'Xiaohu'
xiaohu.print_name()

Xiaohu

所以这个self就用于在类的内部指向对象本身,因为类函数的输入来自与该 类的某个变量/对象 的值,这也是Python面向对象编程“多态”的一种体现

我们还可以给 student 创建一个用于更改成绩的方法,这样我们后续就不需要通过赋值符号更改对象内的数据:

注意 本例笔者进行了修改,与原教程有些许不同,能理解意思就好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class student():
## 定义一个修改对象数据值的函数
def change_score(self, course_name, score):
if course_name == 'math':
self.math_score = score
elif course_name == 'language':
self.language_score = score
## 如果输入的 course_name 不是 math 或者 language,则输出错误信息
else:
print(course_name, " course is still not in current system")

def print_name(self,):
print(self.name)

name = 'Undifined'
math_score = -1
language_score = -1
1
2
3
4
5
xiaohu = student()
xiaohu.name = 'Xiaohu'
xiaohu.change_score('math', 65)
xiaohu.change_score('language',55)
xiaohu.change_score('physics',48)

physics course is still not in current system

假设当我们有了十多种课程后,采用 change_score 函数要比直接为一个个课程的成绩赋值更加优雅,用户不再需要了解 student 类中有定义哪些变量等复杂细节,只需要了解 change_score 函数的用法便可以更改学生成绩,这体现了面向对象编程的“封装性”。

__init__方法

注意,此方法的方法名中,开头和结尾各有 2 个下划线,且中间不能有空格。

其实 Python 类中有一种 __init__ 方法专门用于初始化对象。这个方法在通过类创建对象时被自动调用,并按照你的想法初始化该对象。下面我们通过 __init__ 方法重新定义 student 类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class student():
## 定义 __init__ 方法,通过该方法的参数输入初始值,在该方法内部为变量赋值
def __init__(self, name, math_score, language_score):
self.name = name
self.math_score = math_score
self.language_score = language_score

def change_score(self, course_name, score):
if course_name == 'math':
self.math_score = score
elif course_name == 'language':
self.language_score = score
## 如果输入的 course_name 不是 math 或者 language,则输出错误信息
else:
print(course_name, " course is still not in current system")

def print_name(self,):
print(self.name)

name = 'Undifined'
math_score = -1
language_score = -1

在定义了 __init__ 方法后,我们通过在类后面的小括号内传递参数的方式初始化对象:

注意,是初始化。是在类的小括号里面,直接根据前面__init__的类函数格式填充参数。

1
2
xiaohu = student('XiaoHu',65,55)
xiaohu.print_name()

XiaoHu

python的魔法函数总被双下划线包围,它们可以给你的类增加特殊的方法。如果你的对象实现了这些方法中的一个,那么这个方法就会在特殊情况下被调用,你可以定义想要的行为,而这一切都是自动发生的。

万物皆对象(暂略,重要性不大)

Python 中万物皆源于对象。下面我们在面向对象编程的角度回顾之前学习的变量、函数以及数据结构。

重识变量

在 Python 中所有变量都是对象

文件

open()

为了测试 python 中的文件操作,我们先在当前目录新建一个test.txt 文件,内容随意。

open(file, mode) 函数主要有 file 和 mode 两个参数,其中 file 为需要读写文件的路径。mode 为读取文件时的模式,常用的模式有以下几个:

  • r:以字符串的形式读取文件。
  • rb:以二进制的形式读取文件。
  • w:写入文件。
  • a:追加写入文件。

不同模式下返回的文件对象功能也会不同。

1
2
file = open('test.txt', 'r')
print(type(file))

<class ‘_io.TextIOWrapper’>

文件对象

open()会返回一个 文件对象,对于操作文件对象,有一些常用方法。

  • close( ): 关闭文件
  • 在 r 与 rb 模式下:
    • read(): 读取整个文件
    • readline(): 读取文件的一行
    • reallines(): 读取文件的所有行
  • 在 w 与 a 模式下:
    • write():
    • weitelines():

下面我们通过实例学习这几种方法:

因为本页面不能运行代码,Jupyter Notebook运行结果不直观,下面直接放上截图

1
2
3
## 通过 read 方法读取整个文件
content = file.read()
print(content)

1
2
3
## 通过 readline() 读取文件的一行
content = file.readline()
print(content)

发现什么都没有输出,为什么?

你可以理解 open 函数返回的是一个指针,类似于你在 Microsolf Word 文档里编辑文档时闪烁的光标。在执行过 file.read( ) 操作后,由于读取了整个文件,这个指针已经来到了文件末尾,因此 file.readline( ) 没有获取到文件的内容。这种情况我们可以通过 close 方法关闭文件后再重新打开。

1
2
3
4
5
6
## 关闭之前打开的 test.txt 文件
file.close()
## 重新打开
file = open('test.txt', 'r')
content = file.readline()
print(content)

因此在操作文件时,我们一定要注意每次操作结束后,及时通过 close( ) 方法关闭文件。

1
2
3
4
5
6
7
8
## 以 w 模式打开文件test.txt
file = open('test.txt', 'w')
## 创建需要写入的字符串变量 在字符串中 \n 代表换行(也就是回车)
content = 'Hello world!\nHello Python!!\n'
## 写入到 test.txt 文件中
file.write(content)
## 关闭文件对象
file.close()

追加就用a模式哈,就不演示了。

模块

模块可以帮助我们把一个代码添加到另一个代码中,真正实现了工具等复用性。(其实跟C/C++中写入头文件再include的方式差不多)

编写模块的方式有很多,其中最简单的模块就是创建一个包含很多函数、变量以及类并以 .py 为后缀的文件。下面我们把上一节中实现的 class 类保存在 student.py 文件中:

ps.这个图片是从教程里下载下来的

使用 import 关键字可以把一个模块引入到一个程序来使用它的功能。记得在上一节中我们说过一个程序也可以是一个对象,这时 student.py 程序就成了一个对象,而里面的 student 类便成了它的对象变量。

1
2
3
4
5
import student #.py省略了
xiaohu = student.student('XiaoHu',65,55)
#为什么有两个student?
##前一个student是 student.py程序,后一个student是该程序里面的student类
print(xiaohu)

(‘XiaoHu’, 65, 55)

当我们只需要模块中的几个函数或类时,也可以采用 from model_name import xxx 的写法导入指定部分:

1
2
3
4
5
## 仅导入 student 类
from student import student
## 这时直接通过类名,不需要使用模块名
xiaohu = student('XiaoHu', 65, 55)
print(xiaohu)

(‘XiaoHu’, 65, 55)

结语

大致就这些,Python语言还是比较好上手的,通读完教程后,希望能对后续学习提供帮助!