Python基础

最流行的脚本语言,最适合爬虫的语言

字符串

**find()**:检测某个⼦串是否包含在这个字符串中,如果在返回这个⼦串开始的位置下标,否则则返回-1

**index()**:检测某个⼦串是否包含在这个字符串中,如果在返回这个⼦串开始的位置下标,否则报异常

1
2
字符串序列.find(⼦串, 开始位置下标, 结束位置下标)
字符串序列.index(⼦串, 开始位置下标, 结束位置下标)

开始和结束位置下标可以省略表示在整个字符串序列中

**rfind()**: 和find()功能相同,但查找⽅向为右侧开始

**rindex()**:和index()功能相同,但查找⽅向为右侧开始

**count()**:返回某个⼦串在字符串中出现的次数

1
2
3
字符串序列.rfind(⼦串, 开始位置下标, 结束位置下标)
字符串序列.rindex(⼦串, 开始位置下标, 结束位置下标)
字符串序列.count(⼦串, 开始位置下标, 结束位置下标)

**replace()**:替换

**split()**:按照指定字符分割字符串

**join()**:⽤⼀个字符或⼦串合并字符串,即是将多个字符串合并为⼀个新的字符串

1
2
3
字符串序列.replace(旧⼦串, 新⼦串, 替换次数)
字符串序列.split(分割字符, num)
字符或⼦串.join(多字符串组成的序列)

**capitalize()**:将字符串第⼀个字符转换成⼤写

**title()**:将字符串每个单词⾸字⺟转换成⼤写

**lower()**:将字符串中⼤写转⼩写

**upper()**:将字符串中⼩写转⼤写

1
2
3
4
字符串.capitalize()
字符串.title()
字符串.lower()
字符串.upper()

**startswith()**:检查字符串是否是以指定⼦串开头,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查

**endswith()**::检查字符串是否是以指定⼦串结尾,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查

1
2
字符串序列.startswith(⼦串, 开始位置下标, 结束位置下标)
字符串序列.endswith(⼦串, 开始位置下标, 结束位置下标)

开始和结束位置下标可以省略表示在整个字符串序列中

**isalpha()**:如果字符串⾄少有⼀个字符并且所有字符都是字⺟则返回 True, 否则返回 False

**isalnum()**:如果字符串⾄少有⼀个字符并且所有字符都是字⺟或数字则返 回 True,否则返回False

**isspace()**:如果字符串中只包含空⽩,则返回 True,否则返回 False

1
2
3
字符串.isalpha()
字符串.isalnum()
字符串.isspace()

列表

**index()**:返回指定数据所在位置的下标

1
列表序列.index(数据, 开始位置下标, 结束位置下标)

如果查找的数据不存在则报错

**count()**:统计指定数据在当前列表中出现的次数

**len()**:访问列表⻓度,即列表中数据的个数

1
2
列表.count("判断的字符串")
len(列表)

in:判断指定数据在某个列表序列,如果在返回True,否则返回False

not in:判断指定数据不在某个列表序列,如果不在返回True,否则返回False

1
2
字符串1 in 列表
字符串1 not in 列表

append():列表结尾追加数据,如果append()追加的数据是⼀个序列,则追加整个序列到列表

**extend()**:列表结尾追加数据,如果数据是⼀个序列,则将这个序列的数据逐⼀添加到列表

1
2
列表.append(数据)
列表.extend((数据)

列表追加数据的时候,直接在原列表⾥⾯追加了指定数据,即修改了原列表,故列表为可变类型数据

1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']

name_list.append(['xiaoming', 'xiaohong'])

# 结果:['Tom', 'Lily', 'Rose', ['xiaoming', 'xiaohong']]
1
2
3
4
5
name_list = ['Tom', 'Lily', 'Rose']

name_list.extend(['xiaoming', 'xiaohong'])

# 结果:['Tom', 'Lily', 'Rose', 'xiaoming', 'xiaohong']

**insert()**:指定位置新增数据

1
列表.insert(位置下标, 数据)

del 删除⽬标

1
2
del 列表
del 列表[下标]

**pop()**:删除指定下标的数据(默认为最后⼀个),并返回该数据

**remove()**:移除列表中某个数据的第⼀个匹配项

**clear()**:清空列表

1
2
3
列表.pop(下标)
列表.remove(数据)
列表.clear()

修改指定下标数据

1
列表[下标] = 新的值

**reverse()**:逆置

1
2
3
4
5
num_list = [1, 5, 2, 3, 6, 8]

num_list.reverse()

# 结果:[8, 6, 3, 2, 5, 1]

**sort()**:排序

reverse表示排序规则,reverse = True 降序, reverse = False 升序(默认)

1
列表.sort( key=None, reverse=False)

**copy()**:复制

1
列表.copy()

元组

列表可以⼀次性存储多个数据,但是列表中的数据允许更改,元组中的数据不允许修改

定义元组使⽤⼩括号,且逗号隔开各个数据,数据可以是不同的数据类型

如果元组里面有列表,修改列表里面的数据则是⽀持的

1
2
3
4
# 多个数据元组
t1 = (10, 20, 30)
# 单个数据元组
t2 = (10,)

下标查找

1
元组[下标]

**index()**:查找某个数据,如果数据存在返回对应的下标,否则报错,语法和列表、字符串的index⽅法相同

**count()**:统计某个数据在当前元组出现的次数

**len()**:统计元组中数据的个数

1
2
3
元组.index(字符串)
元组.count(字符串)
len(元组)

字典

字典为可变类型

符号为大括号

数据为键值对形式出现

各个键值对之间⽤逗号隔开

1
2
3
4
# 有数据字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
# 空字典
dict2 = {}

新增数据

如果key存在则修改这个key对应的值;如果key不存在则新增此键值对

1
字典序列[key] =

del() / del:删除字典或删除字典中指定键值对

**clear()**:清空字典

1
2
del 字典[key]
字典.clear()

**get()**:获取值

如果当前查找的key不存在则返回第⼆个参数(默认值),如果省略第⼆个参数,则返回None

1
字典.get(key, 默认值)

**keys()**:获取所有的key

**values()**:获取所有的值

**items()**:字典转换为列表套元组

1
2
3
字典.keys()
字典.values()
字典.items()

遍历字典的key和value

1
2
3
4
5
6
7
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for key in dict1.keys():
print(key)

dict2 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for value in dict2.values():
print(value)

遍历字典中的元素和键值对

1
2
3
4
5
6
7
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for item in dict1.items():
print(item)

dict2 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for key, value in dict2.items():
print(f'{key} = {value}')

集合

创建集合使⽤ {} 或 set() , 但是如果要创建空集合只能使用 set() ,因为 {} ⽤来创建空字典

集合可以去掉重复数据

集合数据是无序的,故不⽀持下标

**add()**:增加数据

因为集合有去重功能,所以,当向集合内追加的数据是当前集合已有数据的话,则不进行任何操作

1
集合.add(值)

**update()**:追加的数据是序列

1
2
3
4
5
s1 = {10, 20}
# s1.update(100) # 报错
s1.update([100, 200])
s1.update('abc')
print(s1)

**remove()**:删除集合中的指定数据,如果数据不存在则报错

**discard()**:删除集合中的指定数据,如果数据不存在也不会报错

**pop()**:随机删除集合中的某个数据,并返回这个数据

1
2
3
集合.remove(值)
集合.discard(值)
集合.pop()

in:判断数据在集合序列

not in:判断数据不在集合序列

1
2
值 in 集合
not in 集合

公共操作

运算符 描述 支持的容器类型
+ 合并 字符串、列表、元组
* 复制 字符串、列表、元组
in 元素是否存在 字符串、列表、元组、字典
not in 元素是否不存在 字符串、列表、元组、字典
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
31
32
33
34
35
36
37
38
39
40
41
42
43
# 1. 字符串 
str1 = 'aa'
str2 = 'bb'
str3 = str1 + str2
print(str3) # aabb


# 2. 列表
list1 = [1, 2]
list2 = [10, 20]
list3 = list1 + list2
print(list3) # [1, 2, 10, 20]

# 3. 元组
t1 = (1, 2)
t2 = (10, 20)
t3 = t1 + t2
print(t3) # (10, 20, 100, 200)

# 1. 字符串
print('-' * 10) # ----------

# 2. 列表
list1 = ['hello']
print(list1 * 4) # ['hello', 'hello', 'hello', 'hello']

# 3. 元组
t1 = ('world',)
print(t1 * 4) # ('world', 'world', 'world', 'world')

# 1. 字符串
print('a' in 'abcd') # True
print('a' not in 'abcd') # False

# 2. 列表
list1 = ['a', 'b', 'c', 'd']
print('a' in list1) # True
print('a' not in list1) # False

# 3. 元组
t1 = ('a', 'b', 'c', 'd')
print('aa' in t1) # False
print('aa' not in t1) # True
函数 描述
len() 计算容器中元素个数
del 或 del() 删除
max() 返回容器中元素最大值
min() 返回容器中元素最小值
range(start, end, step) 生成从start到end的数字,步长为 step,供for循环使用
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中

len()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1. 字符串
str1 = 'abcdefg'
print(len(str1)) # 7

# 2. 列表
list1 = [10, 20, 30, 40]
print(len(list1)) # 4

# 3. 元组
t1 = (10, 20, 30, 40, 50)
print(len(t1)) # 5

# 4. 集合
s1 = {10, 20, 30}
print(len(s1)) # 3

# 5. 字典
dict1 = {'name': 'Rose', 'age': 18}
print(len(dict1)) # 2

del()

1
2
3
4
5
6
7
8
9
# 1. 字符串
str1 = 'abcdefg'
del str1
print(str1)

# 2. 列表
list1 = [10, 20, 30, 40]
del(list1[0])
print(list1) # [20, 30, 40]

max()和min()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 字符串
str1 = 'abcdefg'
print(max(str1)) # g

# 2. 列表
list1 = [10, 20, 30, 40]
print(max(list1)) # 40

# 1. 字符串
str1 = 'abcdefg'
print(min(str1)) # a

# 2. 列表
list1 = [10, 20, 30, 40]
print(min(list1)) # 10

range()

range()生成的序列不包含end数字

1
2
3
4
5
6
7
8
9
10
11
# 1 2 3 4 5 6 7 8 9
for i in range(1, 10, 1):
print(i)

# 1 3 5 7 9
for i in range(1, 10, 2):
print(i)

# 0 1 2 3 4 5 6 7 8 9
for i in range(10):
print(i)

enumerate()

start参数用来设置遍历数据的下标的起始值,默认为0

1
enumerate(可遍历对象, start=0)
1
2
3
4
5
6
7
list1 = ['a', 'b', 'c', 'd', 'e']

for i in enumerate(list1):
print(i)

for index, char in enumerate(list1, start=1):
print(f'下标是{index}, 对应的字符是{char}')

tuple()

将某个序列转换成元组

1
2
3
4
5
list1 = [10, 20, 30, 40, 50, 20]
s1 = {100, 200, 300, 400, 500}

print(tuple(list1))
print(tuple(s1))

list()

将某个序列转换成列表

1
2
3
4
5
t1 = ('a', 'b', 'c', 'd', 'e')
s1 = {100, 200, 300, 400, 500}

print(list(t1))
print(list(s1))

set()

将某个序列转换成集合

集合可以快速完成列表去重,集合不支持下标

1
2
3
4
5
list1 = [10, 20, 30, 40, 50, 20]
t1 = ('a', 'b', 'c', 'd', 'e')

print(set(list1))
print(set(t1))

推导式

1
2
3
4
5
6
7
8
# 列表推导式
[xx for xx in range()]

# 字典推导式
{xx1: xx2 for ... in ...}

# 集合推导式
{xx for xx in ...}

列表推导式

1
list1 = [i for i in range(10)]
1
2
3
4
5
# 创建0-10的偶数列表
# range()步长实现
list1 = [i for i in range(0, 10, 2)]
# if实现
list1 = [i for i in range(10) if i % 2 == 0]

字典推导式

1
2
3
# 创建一个字典:字典key是1-5数字,value是这个数字的2次方
dict1 = {i: i**2 for i in range(1, 5)}
print(dict1) # {1: 1, 2: 4, 3: 9, 4: 16}
1
2
3
4
5
6
7
8
9
10
11
12
13
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']

# 合并两个字典
dict1 = {list1[i]: list2[i] for i in range(len(list1))}
print(dict1)

# 提取字典中目标数据
counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99}

# 需求:提取上述电脑数量大于等于200的字典数据
count1 = {key: value for key, value in counts.items() if value >= 200}
print(count1) # {'MBP': 268, 'DELL': 201}

集合推导式

1
2
3
4
# 创建一个集合,数据为下方列表的2次方
list1 = [1, 1, 2]
set1 = {i ** 2 for i in list1}
print(set1) # {1, 4}

拆包和交换变量值

元组

1
2
3
4
5
6
7
def return_num():
return 100, 200


num1, num2 = return_num()
print(num1) # 100
print(num2) # 200

字典

1
2
3
4
5
6
7
8
9
dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1

# 对字典进行拆包,取出来的是字典的key
print(a) # name
print(b) # age

print(dict1[a]) # TOM
print(dict1[b]) # 18

函数

定义函数

在Python中,函数必须先定义后使⽤

局部变量是定义在函数体内的变量,即只在函数体内部⽣效

全局变量是定义在函数体外的变量,在全局有效

1
2
3
4
5
def 函数名(参数):
代码1
代码2
......
return

函数参数

位置参数

调用函数时根据函数定义的参数位置来传递参数

传递和定义参数的顺序及个数必须一致

1
2
3
4
5
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')


user_info('TOM', 20, '男')

关键字参数

函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求

1
2
3
4
5
6
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')


user_info('Rose', age=20, gender='女')
user_info('小明', gender='男', age=16)

缺省参数

缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值

所有位置参数必须出现在默认参数前,包括函数定义和调用
函数调用时,如果为缺省参数传值则修改默认参数值;否则使用这个默认值

1
2
3
4
5
6
def user_info(name, age, gender='男'):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')


user_info('TOM', 20)
user_info('Rose', 18, '女')

不定长参数

不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便

传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 包裹位置传递
def user_info(*args):
print(args)


# ('TOM',)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)

# =============================

# 包裹关键字传递
def user_info(**kwargs):
print(kwargs)


# {'name': 'TOM', 'age': 18, 'id': 110}
user_info(name='TOM', age=18, id=110)

lambda

基础

lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用

lambda表达式能接收任何数量的参数但只能返回一个表达式的值

1
lambda 参数列表 : 表达式
1
2
3
4
5
6
7
8
9
# 计算a+b
# 函数

def add(a, b):
return a + b
result = add(1, 2)

# lambda
result = (lambda a, b: a + b)(1, 2)

参数形式

无参数

1
2
fn1 = lambda: 100
print(fn1())

一个参数

1
2
fn1 = lambda a: a
print(fn1('hello world'))

默认参数

1
2
fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))

可变参数:*args

1
2
fn1 = lambda *args: args
print(fn1(10, 20, 30))

这里的可变参数传入到lambda之后,返回值为元组

可变参数:**kwargs

1
2
fn1 = lambda **kwargs: kwargs
print(fn1(name='python', age=20))

高阶函数

把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式

map()

map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回

1
2
3
4
5
6
7
8
9
10
# 计算list1序列中各个数字的2次方
list1 = [1, 2, 3, 4, 5]

def func(x):
return x ** 2

result = map(func, list1)

print(result) # <map object at 0x0000013769653198>
print(list(result)) # [1, 4, 9, 16, 25]

reduce()

reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。

reduce()传入的参数func必须接收2个参数

1
2
3
4
5
6
7
8
9
10
11
# 计算list1序列中各个数字的累加和
import functools

list1 = [1, 2, 3, 4, 5]

def func(a, b):
return a + b

result = functools.reduce(func, list1)

print(result) # 15

filter()

filter(func, lst)函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象。如果要转换为列表, 可以使用 list() 来转换

1
2
3
4
5
6
7
8
9
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def func(x):
return x % 2 == 0

result = filter(func, list1)

print(result) # <filter object at 0x0000017AF9DC3198>
print(list(result)) # [2, 4, 6, 8, 10]

文件操作

打开

在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件

1
open(name, mode)

name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)
mode:设置打开文件的模式(访问模式):只读、写入、追加等

打开文件模式

模式 描述
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
w+ 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

写入

1
对象对象.write('内容')
1
2
3
4
5
6
7
8
# 1. 打开文件
f = open('test.txt', 'w')

# 2.文件写入
f.write('hello world')

# 3. 关闭文件
f.close()

wa模式:如果文件不存在则创建该文件;如果文件存在,w模式先清空再写入,a模式直接末尾追加
r模式:如果文件不存在则报错

读取

1
⽂件对象.read(num)

num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据

**readlines()**:可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素

1
2
3
4
5
6
7
8
f = open('test.txt')
content = f.readlines()

# ['hello world\n', 'abcdefg\n', 'aaa\n', 'bbb\n', 'ccc']
print(content)

# 关闭文件
f.close()

**readline()**:一次读取一行内容

1
2
3
4
5
6
7
8
9
10
f = open('test.txt')

content = f.readline()
print(f'第一行:{content}')

content = f.readline()
print(f'第二行:{content}')

# 关闭文件
f.close()

文件备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
old_name = input('请输入您要备份的文件名:')

index = old_name.rfind('.')


if index > 0:
postfix = old_name[index:]

new_name = old_name[:index] + '[备份]' + postfix

old_f = open(old_name, 'rb')
new_f = open(new_name, 'wb')

while True:
con = old_f.read(1024)
if len(con) == 0:
break
new_f.write(con)

old_f.close()
new_f.close()

文件和文件夹的操作

在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤

  1. 导入os模块
1
import os
  1. 使用os模块相关功能
1
os.函数名()

文件重命名

1
os.rename(目标文件名, 新文件名)

删除文件

1
os.remove(目标文件名)

创建文件夹

1
os.mkdir(文件夹名字)

删除文件夹

1
os.rmdir(文件夹名字)

获取当前目录

1
os.getcwd()

改变默认目录

1
os.chdir(目录)

获取目录列表

1
os.listdir(目录)

类和对象

定义类

不由任意内置类型派生出的类,称之为经典类

1
2
3
class 类名():
代码
......

创建对象

创建对象的过程也叫实例化对象

1
对象名 = 类名()
1
2
3
4
5
6
7
8
# 创建对象
haier1 = Washer()

# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)

# haier对象调用实例方法
haier1.wash()

self

self指的是调用该函数的对象

打印对象和self得到的结果是一致的,都是当前对象的内存中存储地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1. 定义类
class Washer():
def wash(self):
print('我会洗衣服')
# <__main__.Washer object at 0x0000024BA2B34240>
print(self)


# 2. 创建对象
haier1 = Washer()
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
# haier1对象调用实例方法
haier1.wash()


haier2 = Washer()
# <__main__.Washer object at 0x0000022005857EF0>
print(haier2)

魔法方法

init()

__init__()方法的作用:初始化对象

__init__()方法,在创建一个对象时默认被调用,不需要手动调用
__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去

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
31
32
33
class Washer():

# 定义初始化功能的函数
def __init__(self):
# 添加实例属性
self.width = 500
self.height = 800


def print_info(self):
# 类里面调用实例属性
print(f'宽度是{self.width}, 高度是{self.height}')


class Washer2():

# 定义初始化功能的函数
def __init__(self,width,height):
# 添加实例属性
self.width = width
self.height = height


def print_info(self):
# 类里面调用实例属性
print(f'宽度是{self.width}, 高度是{self.height}')


haier1 = Washer()
haier1.print_info()

# 必须传入参数
haier2 = Washer2(100,200)

str()

当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__方法,那么就会打印从在这个方法中 return 的数据

1
2
3
4
5
6
7
8
9
10
11
12
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height

def __str__(self):
return '打印'


haier1 = Washer(10, 20)
# 打印
print(haier1)

del()

当删除对象时,python解释器也会默认调用__del__()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height

def __del__(self):
print(f'{self}对象已经被删除')


haier1 = Washer(10, 20)

# <__main__.Washer object at 0x0000026118223278>对象已经被删除
del haier1

面向对象三大特性

封装

  • 将属性和方法书写到类的里面的操作即为封装
  • 封装可以为属性和方法添加私有权限

继承

  • 子类默认继承父类的所有属性和方法
  • 子类可以重写父类属性和方法

多态

  • 传入不同的对象,产生不同的结果

继承

继承的特点

  • 子类默认拥有父类的所有属性和方法
  • 子类重写父类同名方法和属性
  • 子类调用父类同名方法和属性

super()方法快速调用父类方法

私有权限

  • 不能继承给子类的属性和方法需要添加私有权限
  • 语法
1
2
3
4
5
6
7
class 类名():
# 私有属性
__属性名 = 值

# 私有方法
def __函数名(self):
代码

多态

多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)

定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果

实现步骤:

  • 定义父类,并提供公共方法
  • 定义子类,并重写父类方法
  • 传递子类对象给调用者,可以看到不同子类执行效果不同
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
class Dog(object):
def work(self): # 父类提供统一的方法,哪怕是空方法
print('指哪打哪...')


class ArmyDog(Dog): # 继承Dog类
def work(self): # 子类重写父类同名方法
print('追击敌人...')


class DrugDog(Dog):
def work(self):
print('追查毒品...')


class Person(object):
def work_with_dog(self, dog): # 传入不同的对象,执行不同的代码,即不同的work函数
dog.work()


ad = ArmyDog()
dd = DrugDog()

daqiu = Person()
daqiu.work_with_dog(ad)
daqiu.work_with_dog(dd)

类方法

1
2
3
@classmethod
def xx():
代码

静态方法

1
2
3
@staticmethod
def xx():
代码

异常和导包

异常

语法

1
2
3
4
5
6
7
8
try:
可能发生异常的代码
except:
如果出现异常执行的代码
else:
没有异常执行的代码
finally:
无论是否异常都要执行的代码

捕获异常

1
2
3
4
5
except 异常类型:
代码

except 异常类型 as xx:
代码

自定义异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 自定义异常类
class 异常类类名(Exception):
代码

# 设置抛出异常的描述信息
def __str__(self):
return ...


# 2. 抛出异常
raise 异常类名()

# 捕获异常
except Exception...

模块

导入模块方法

1
2
3
4
5
import 模块名

from 模块名 import 目标

from 模块名 import *

导入包

1
2
3
import 包名.模块名

from 包名 import *
  • __all__ = [] :允许导入的模块或功能列表

进程和线程

多进程

1
2
#导入进程包
import multiprocessing

Process([group [, target [, name [, args [, kwargs]]]]])

  • group:指定进程组,目前只能使用None
  • target:执行的目标任务名
  • name:进程名字
  • args:以元组方式给执行任务传参
  • kwargs:以字典方式给执行任务传参

Process创建的实例对象的常用方法

  • start():启动子进程实例(创建子进程)
  • join():等待子进程执行结束
  • terminate():不管任务是否完成,立即终止子进程

Process创建的实例对象的常用属性:

  • name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
1
2
3
import os
os.getpid() # 表示获取当前进程编号
os.getppid() # 表示获取当前父进程编号

简单使用

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
import multiprocessing
import time


# 跳舞任务
def dance():
for i in range(5):
print("跳舞中...")
time.sleep(0.2)


# 唱歌任务
def sing():
for i in range(5):
print("唱歌中...")
time.sleep(0.2)

if __name__ == '__main__':
# 创建跳舞的子进程
# group: 表示进程组,目前只能使用None
# target: 表示执行的目标任务名(函数名、方法名)
# name: 进程名称, 默认是Process-1, .....
dance_process = multiprocessing.Process(target=dance, name="myprocess1")
sing_process = multiprocessing.Process(target=sing)

# 启动子进程执行对应的任务
dance_process.start()
sing_process.start()

注意

进程之间不共享全局变量

主进程会等待所有的子进程执行结束再结束

多线程

1
2
#导入线程模块
import threading

Thread([group [, target [, name [, args [, kwargs]]]]])

  • group: 线程组,目前只能使用None
  • target: 执行的目标任务名
  • args: 以元组的方式给执行任务传参
  • kwargs: 以字典方式给执行任务传参
  • name: 线程名,一般不用设置

启动线程使用start方法

简单使用

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
31
32
33
import threading
import time

# 唱歌任务
def sing():
# 扩展: 获取当前线程
# print("sing当前执行的线程为:", threading.current_thread())
for i in range(3):
print("正在唱歌...%d" % i)
time.sleep(1)

# 跳舞任务
def dance():
# 扩展: 获取当前线程
# print("dance当前执行的线程为:", threading.current_thread())
for i in range(3):
print("正在跳舞...%d" % i)
time.sleep(1)


if __name__ == '__main__':
# 扩展: 获取当前线程
# print("当前执行的线程为:", threading.current_thread())
# 创建唱歌的线程
# target: 线程执行的函数名
sing_thread = threading.Thread(target=sing)

# 创建跳舞的线程
dance_thread = threading.Thread(target=dance)

# 开启线程
sing_thread.start()
dance_thread.start()

注意

线程之间执行是无序的

主线程会等待所有的子线程执行结束再结束

线程之间共享全局变量

线程之间共享全局变量数据出现错误问题

闭包和装饰器

闭包

在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包

闭包构成的条件

  • 在函数嵌套(函数里面再定义函数)的前提下
  • 内部函数使用了外部函数的变量(还包括外部函数的参数)
  • 外部函数返回了内部函数

闭包的作用:闭包可以保存外部函数内的变量,不会随着外部函数调用完而销毁

1
2
3
4
5
6
7
8
9
# 外部函数
def test1(a):
b = 10
# 内部函数
def test2():
# 内部函数使用了外部函数的变量或者参数
print(a, b)
# 返回内部函数, 这里返回的内部函数就是闭包实例
return test2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 定义一个外部函数
def func_out(num1):
# 定义一个内部函数
def func_inner(num2):
# 内部函数使用了外部函数的变量(num1)
result = num1 + num2
print("结果是:", result)
# 外部函数返回了内部函数,这里返回的内部函数就是闭包
return func_inner

# 创建闭包实例
f = func_out(1)
# 执行闭包
f(2)
f(3)

'''
结果
结果是: 3
结果是: 4
'''

装饰器

给已有函数增加额外功能的函数,它本质上就是一个闭包函数

功能

  • 不修改已有函数的源代码
  • 不修改已有函数的调用方式
  • 给已有函数增加额外的功能
1
2
3
4
5
6
def decorator(fn): # fn:目标函数.
def inner():
'''执行函数之前'''
fn() # 执行被装饰的函数
'''执行函数之后'''
return inner
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 添加一个登录验证的功能
def check(fn):
def inner():
print("请先登录....")
fn()
return inner


def comment():
print("发表评论")

# 使用装饰器来装饰函数
comment = check(comment)
comment()

'''
结果
请先登录....
发表评论
'''

语法糖写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 添加一个登录验证的功能
def check(fn):
print("装饰器函数执行了")
def inner():
print("请先登录....")
fn()
return inner

# 使用语法糖方式来装饰函数
@check
def comment():
print("发表评论")


comment()

# @check 等价于 comment = check(comment)

多个装饰器使用

多个装饰器的装饰过程是: 离函数最近的装饰器先装饰,然后外面的装饰器再进行装饰,由内到外的装饰过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def make_div(func):
"""对被装饰的函数的返回值 div标签"""
def inner(*args, **kwargs):
return "<div>" + func() + "</div>"
return inner


def make_p(func):
"""对被装饰的函数的返回值 p标签"""
def inner(*args, **kwargs):
return "<p>" + func() + "</p>"
return inner


# 装饰过程: 1 content = make_p(content) 2 content = make_div(content)
# content = make_div(make_p(content))
@make_div
@make_p
def content():
return "人生苦短"

result = content()

print(result)

带有参数的装饰器

装饰器只能接收一个参数,并且还是函数类型

在装饰器外面再包裹上一个函数,让最外面的函数接收参数,返回的是装饰器,因为@符号后面必须是装饰器实例

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
31
32
33
34
# 添加输出日志的功能
def logging(flag):

def decorator(fn):
def inner(num1, num2):
if flag == "+":
print("--正在努力加法计算--")
elif flag == "-":
print("--正在努力减法计算--")
result = fn(num1, num2)
return result
return inner

# 返回装饰器
return decorator


# 使用装饰器装饰函数
@logging("+")
def add(a, b):
result = a + b
return result


@logging("-")
def sub(a, b):
result = a - b
return result

result = add(1, 2)
print(result)

result = sub(1, 2)
print(result)

相关文章

Python爬虫

Python反爬解决方案

Mongodb和Python交互

Scrapy爬虫