1 下载安装 Anaconda
- 去官网下载安装包,双击安装包安装,安装路径可自定义安装。
- 安装完成后设置环境变量,在环境变量中的 path 中添加 Anaconda 的安装路径及路径下的 Scripts 的路径
- 然后打开 cmd 命令窗口,输入 conda --version 校验是否安装成功
- 启动 Anaconda ,在电脑搜索的地方搜索 “Jupyter Notebook” 进行启动。
2 基础知识
2.1 print:用于字符串打印
语法:
print(value,...,sep='',end='')
# 1. value:输入一个或多个要打印的字符串
# 2. sep:代表可自定义 value 之间的符号,默认为空格
# 3. end:代表可自定义 value 结尾的符号,默认为换行符号
print('lemon','apple','banana',sep=',',end='.')
2.2 注释与换行操作
单行注释:
print('hello','world') # 向屏幕输出 hello world
多行注释:
'''
先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。
然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。
诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
'''
"""
宫中府中,俱为一体,陟罚臧否,不宜异同。
若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
"""
print('侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。')
print('愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。')
print('将军向宠,性行淑均,晓畅军事,试用于昔日,先帝称之曰能,是以众议举宠为督。')
换行:
print('愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。\
亲贤臣,远小人,此先汉所以兴隆也;\
亲小人,远贤臣,此后汉所以倾颓也。\
先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。\
侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。')
2.3 单引号、双引号及转义字符
print('臣本布衣,躬耕于南阳')
print("臣本布衣,躬耕于南阳")
print(''' I'm pythonic,I said:"Practice makes perfect" ''')
print(""" I'm pythonic,I said:"Practice makes perfect" """)
# 用反斜杠(\)转义特殊字符
print('\n')
print('\\n')
# 可以用 r 和 R 来定义原始字符串
print(r'\\n') # 打印的是 \\n
print(R'\\n') # 打印的是 \\n
2.4 运算符和数学函数
运算符:
# 乘方
4 ** 4 # 表示4的4次方,结果:256
# 取整
20 // 6 # 结果:3
# round 四舍五入
round(8.9) # 四舍五入保留到整数位
round(10.671,2) # 四舍五入保留小数点后两位
# abs绝对值取整
abs(-1)
math 数学函数:
import math
math.ceil(5.01) # 向上取整
math.floor(5.99) # 向下取整
math.trunc(10.9) # 截取整数位
math.pow(2,4) # 幂运算,表示2的4次方
2.5 字符串
特点:由单引号、双引号、三个单引号、三个双引号 组成
'A' + 'B' # 结果:AB
'A' * 3 # 结果:AAA
'python'[1] # 结果:y
'python'[-2] # 结果:o
'python'[1:4] # 结果:yth
'python'[2:] # 结果:thon
-
String.strip([chars]) :
- chars为空:去除头尾空白符(\n、\r、\t、'',即换行、回车、制表符、空格)
- chars不为空:将chars拆成一个一个字符,去除头尾指定的字符
' abc123abc '.strip() # 结果:'abc123abc'
'abc123abc'.strip('ab') # 结果:'c123abc'
'abc123abc'.strip('ba') # 结果:'c123abc'
'eabc123abc'.strip('ba') # 结果:'eabc123abc'
'abc123cba'.strip('bac') # 结果:'123'
'abc12abc3cba'.strip('bac') # 结果:'12abc3'
- String.lstrip([chars]) :
' abc123abc '.lstrip() # 结果:'abc123abc '
- String.rstrip([chars]) :
' abc123abc '.rstrip() # 结果:' abc123abc'
- 判断字符串开头结尾字符:
'python'.startswith('p') # 结果:true
'python'.endswith('n') # 结果:true
- 返回字符串中字符的位置:
'apple'.find('p') # 结果:1
'apple'.index('p') # 结果:1
'apple'.find('m') # 结果:-1
'apple'.index('m') # 结果:报错
- 字符串替换:
'python'.replace('t','TT') # 结果:'pyTThon'
'python'.replace('python','hello') # 结果:'hello'
- len(S): 返回字符串长度
- S.count('x'): 查找某个字符在字符串里面出现的次数
- S.upper(): 将字符串中小写字母,转为大写字母
- S.lower(): 将字符串中大写字母,转为小写字母
- S.center(n,'-'): 把字符串放中间,两边用-补齐,n为字符串长度,若n小于字符串长度则返回原值
- 字符串格式化:% format
- %s: 使用 str() 函数进行字符串转换
- %d: 转为十进制整数
- %f: 转为浮点数
'hello %s' %('world') # 结果:'hello world'
'hello %s,%s' %('world') # 结果:报错
'hello %s,%s' %('world','apple') # 结果:'hello world,apple'
'I am %{name}s, I am %{age}s years old' %{'name':'cily','age':16} # 结果:'I am cily, I am 16 years old'
'I am %d years old' % (16) # 结果:'I am 16 years old'
'%f' % (3.14) # 结果:'3.140000'
'%.3f' % (3.14) # 结果:'3.140'
'hello {}'.format('world') # 结果:'hello world'
'hello {} {}'.format('world','python') # 结果:'hello world python'
'hello {1} {0}'.format('world','python') # 结果:'hello python world'
'I am {name}, I am {age} years old'.format(name = "cily",age = 16) # 结果:'I am cily, I am 16 years old'
2.6 Number(数字):整形、浮点型、复数
Python数字类型:整形(int)、浮点型(float)、复数(complex)、布尔型(bool)
进制转换:
- bin 转化为二进制 0b1010
- oct 转化为八进制 0o12
- int 转化为十进制 10
- hex 转化为十六进制 0xa
- 浮点型(float):
type(10) # int
type(10.) # float
print(3+1.0) # 4.0
print(type(3+1.0)) # <class 'float'>
# Python 中相除,默认返回浮点型
print(3/1) # 3.0
print(type(3/1)) # <class 'float'>
# 整除
print(3//1) # 3
print(type(3//1)) # <class 'int'>
- 复数(complex):complex([real[,imag]])
complex(3,) # (3+0j)
complex(3,4) # (3+4j)
complex(3,4).real # 实部,结果:3.0
complex(3,4).imag # 虚部,结果:4.0
complex('3',4) # 报错
complex('3+4j') # (3+4j)
complex('3 + 4j') # 报错
- 布尔类型:判断条件是否成立,只有 True、False
int(True) # 1
int(False) # 0
isinstance(1,int) # True
isinstance(0,int) # True
isinstance(True,int) # True
isinstance(False,int) # True
bool(1) # True
bool(0) # False
bool(-1) # True
bool(None) # False
bool() # False
bool('') # False
bool(' ') # True
bool([]) # False
bool({}) # False
2.7 列表、元组、字典
- 列表
# 创建空列表
list[]
[]
# 创建只有一个元素的列表
[1,]
[1]
# 创建包含不同数据类型的列表
['a',1,2,3.14,[1,2,3,4]]
# 列表操作
['a',1,2,3.14,[1,2,3,4]][0] # 'a'
['a',1,3.14,[1,2,3,4]][3][2] # 3
[1,2] + [3.4] # [1,2,3.4]
[1,2] - [3.4] # 报错,列表间不支持相减操作
[1,2] * 5 # [1,2,1,2,1,2,1,2,1,2]
[1,2] / [3.4] # 报错,列表间不支持相除操作
- list.count(x) : 统计列表中 x 出现的次数,若不存在则返回 0
- list.append(x) : 向列表尾部追加成员 x
- list.extend(l): 向列表尾部追加另外一个列表 l
- list.index(x) : 返回参数 x 在列表中的序号,若不存在则报错
- list.insert(index, object) : 在列表指定位置插入数据
- list.pop() : 默认删除列表尾部成员,并返回删除的成员
- list.remove(x) : 删除列表中指定成员(有多个则只删除第一个),若指定成员不存在则报错
- list.reverse() : 将列表中的成员顺序颠倒
- list.sort() : 排序(要求成员间可排序,否则报错)
x = [1,2,3,4,2,5,3,8,2,9,0,19,2,14,12,34,25]
x.count(2) # 4
[1,2,3].append([7,8,9]) # [1,2,3,[7,8,9]]
[1,2,3].extend([7,8,9]) # [1,2,3,7,8,9]
[11,12,13,14].pop() # 14
[11,12,13,14].pop(1) # 12
- 元组(tuple):
元组基本形式:圆括号 () 包围的数据集合,可以通过序号访问元素。一种特殊形式的列表。一但创建不可变。
【注意】:元组的元素不可变,但当元组元素为列表或字典数据类型时,列表或字典内的内容是可以变的。
# 创建空元组
()
tuple()
(1,) # 创建只有一个元素的元组不能省略这个逗号
type((1,)) # tuple
type((1)) # int
a = (1,2,3,[4,5,6])
a[1] = 10 # 报错
a[3][0] = 10 # a的值变为 (1,2,3,[10,5,6])
- 元组常见函数:
- len(tuple) # 返回元组数量
- max(tuple) # 返回元组最大值
- min(tuple) # 返回元组最小值
- tuple(seq) # 将序列转为元组
- 字典基本操作:
{} # 创建空字段
dict() # 创建空字段
fruits = {"lemon":5,"apple":10}
fruits['lemon'] # 5
fruits['pear'] # 通过不存在的键访问成员会报错
fruits['lemon'] = 20
fruits['pear'] = 15
del fruits['pear'] # 删除pear
fruits.clear() # 清空整个字典
del fruits # 删除 fruits
字典的键的数据类型可以是:字符串、数字、元组不可变数据类型,不能为列表类型。
- dict.copy() # 复制字典
- dict.get(key,default=None) # 获取key对应的值,若key不存在则返回default
- dict.items() # 获取由键和值组成的迭代器
- dict.keys() # 获取键的迭代器
- dict.values() # 获取值的迭代器
- dict.pop(key,[default]) # 删除key:value的指定成员对。若key不存在,则返回default
- dict.popitem() # 从字典末尾删除key:value,并返回key:value
- dict.update({key:value}) # 从另外一个字典更新成员(存在则覆盖,若不存在就创建。)
- dict.setdefault(key,default=None) # 若字典存在key,则返回对应的值(不会覆盖原值)。若不存在,则建立一个key:default的字典成员。
fruits1 = {'lemon':5,'apple':10}
fruits2 = fruits1.copy()
fruits1.get('pear','该键不存在')
fruits1.items() # dict_items([{'lemon':5},{'apple':10}])
fruits1.keys() # dict_keys(['lemon', 'apple'])
2.8 Set集合类型
集合(set):无序、不重复的数据集合。无法通过键访问成员。可以使用大括号{}或者set()函数创建集合。
# 注意:创建一个空集合必须用 set() 而不是 {},因为 {} 是创建一个空字典。
type(set()) # set
a = {1,2,3,4}
type(a) # set
b = {1,1,3,3,2,2,4,4} # 最终 b 的值为 {1,3,2,4}
c = ['lemon','lemon','apple','apple']
set(c) # 去重,结果:{'lemon','apple'}
d = {1,2,3,4,5,6}
len(d) # 6
1 in d # True
7 in d # False
d - a # 得出集合间的差集 {5,6}
d & a # 得出集合间的交集 {1,2,3,4}
d | a # 得出集合间的并集 {1,2,3,4,5,6}
2.9 Python 基本数据类型总结
- 数字(Number):整型(int)、浮点型(float)、复数(complex)、布尔型(bool)
- 序列:列表(可变序列)、字符串(不可变序列)、元组(不可变序列)
- 字典:无序,没有索引,通过键值对访问,键是不可变的
- 集合:无序,没有索引,没有重复元素
2.10 变量
命名规则:只能包含字母、数字、下划线,不能以数字开头。最好用小写字母。
关键字:
False、class、finally、is、return、True、continue、for、lambda、try、None、def、from、nonlocal、while、and、del、global、not、with、as、elif、if、or、yield、assert、else、import、pass、break、raise、except、in
2.11 运算符
- 算术运算符:
+-*/%//**
a = {1,2,3,4}
b = {1,2}
a - b # 得出集合间的差集 {3,4}
'python ' * 3 # 字符串 'python python python '
[1,2,3] * 3 # 列表 [1,2,3,1,2,3,1,2,3]
(1,2,3) * 3 # 元组 (1,2,3,1,2,3,1,2,3)
10 // 3 # 取整运算 3
10.0 // 3 # 取整运算 3.0
-
赋值运算符:
=+=-=*=/=%=//+**= -
比较(关系)运算符:
==!=<><>=><=
1 == 1 # True
1 == 1.0 # True
# 不等于 <> 适用于 Python2
# 不等于 != 适用于 Python2、3
'a' < 'b' # True 字符串比较大小通过ASCII码比较,ord('a')为97,ord('b')为98,注意ord()函数参数只能传入一个字符
[1,2,3] == [1,3,2] # False
[1,2,3] < [1,3,2] # True
{1,2,3} == {1,3,2} # True
{1,2,3} < {1,3,2} # False
{'lemon':5,'apple':4} == {'lemon':5} # False
{'lemon':5,'apple':4} < {'lemon':5} # 报错,字典不支持比较大小
- 逻辑运算符:
andornot
# 布尔类型为 0 None 控制(空字符串、空列表、空元组、空字典、空集合)的时候,返回False
bool('') # False
bool(' ') # True
0 and 2 # 0
1 and 2 # 2
2 and 1 # 1
0 or [] # []
[] or 0 # 0
0 or 2 # 2
1 or 2 # 1
not 1 # False
not 0 # True
- 成员运算符:判断一个元素是否在另外一组元素中,返回布尔类型。
innot in
a = 'lemon'
a in 'hello lemon' # True
a not in 'hello lemon' # False
b = 1
b in [1,2,3,4] # True
b in {1,2,3,4} # True
b in (1,2,3,4) # True
# 字典的成员运算,针对的是字典key:value中的key
c = 5
d = {'lemon':5}
c in d # False
e = 'lemon'
e in d # True
- 身份运算符:比较两个对象,内存地址是否相等,返回布尔类型。
isis not
a = 1
b = 1
a is b # True 可通过id(a) 和 id(b) 来查看内存地址
c = 1.0
a == c # True
a is c # False
d = {1,2,3}
e = {2,1,3}
d == e # True
d is e # False
f = {'lemon':5,'apple':3,'pear':4}
g = {'apple':3,'pear':4,'lemon':5}
f == g # True
f is g # False
- 位运算符:把数字转为二进制运算。
&|^~<<>>
bin(4) # 0b100
bin(5) # 0b101
# & 按位与:两个相应位都为1,则该位为1,否则为0
4 & 5 # 4
int('100',2) # 4
# | 按位或:两个相应位至少有一个为1,则该位为1,否则为0
4 | 5 # 5
int('101',2) # 5
# ^ 按位异或:两个相应位相异的时候,则该位为1,否则为0
4 ^ 5 # 5
int('001',2) # 1
2.12 值类型与引用类型
- 值类型是不可变的:数字、str、tuple
- 引用类型是可改变的:list、dict、set
2.13 if 语句
语法:
if condition:
true_expression
else:
false_expressions
other_expression
if condition1:
expression1
elif condition2:
expression2
elif condition3:
expression3
else:
expressions
a = True
if a:
print('条件成立')
print('if执行完成')
'''
打印结果如下:
条件成立
if执行完成
'''
a = False
if a:
print('条件成立')
print('if执行完成')
'''
打印结果如下:
if执行完成
'''
input() 函数会接收输入数据,返回为 string 类型
num = input('请输入数字:')
# 输入数字5后
num # 5
type(num) # str
num = int(num)
type(num) # int
2.14 for循环 / while 循环
- for循环:循环/遍历一个可迭代对象,主要是用来遍历 序列(列表、字符串、元组)、字典和集合
语法:
for 循环变量 in 可迭代对象:
<语句1>
else:
<语句2>
# else 也可以与 for 循环进行搭配,当 for 循环遍历完成后,执行 else 里面的内容。
遍历字符串:
words = 'I am lemon'
for word in words:
print(word)
print(word,end = '')
列表遍历:
fruits_list = ['banana','mango','lemon']
for i in fruits_list:
print(i)
字典遍历:
fruits_dict = {'banana':5,'mango':1,'lemon':7}
for key in fruits_dict.keys():
print(key)
for val in fruits_dict.values():
print(val)
for key,val in fruits_dict.items():
print(key,val)
complex_list = [['banana','mango','lemon'],[1,2,3]]
for x in complex_list:
for y in x:
print(y)
函数 - range()
语法:
range(start, end[, step])
# start:计数从 start 开始,默认从 0 开始,例如: range(10) 等价于 range(0, 10)
# end:计数到 end 结束,但不包含 end,例如:range(0, 10) 是 [0,1,2,3,4,5,6,7,8,9] 没有 10
# step:步长,默认为1。例如:range(0,10) 等价于 range(0,10,1)
# range 里面只能是整型类型
for 循环变量名 in range(start,end[,step]):
<执行语句1>
else:
<执行语句2>
for i in range(0,10,2):
print(i, end='') # 打印的是 0 2 4 6 8
continue:结束本次循环,进入下一次循环遍历
break:结束当前循环
fruits = ['apple','lemon','pear','lemon','banana','grape','banana','apple']
for i in fruits:
if i == 'lemon':
continue
if i == 'grape':
break
print(i, end='')
4 种常用迭代函数
1、enumerate(seq) # 编号迭代
2、sorted(seq) # 排序迭代
3、reversed(seq) # 翻转迭代
4、zip(seq1,seq2,seq3....) # 并行迭代
seq 为可遍历/可迭代的对象,如列表、字符串、元组
# enumerate 编号迭代:在迭代的时候既返回序列中的编号(默认从0开始),又返回序列中的元素
# 需要两个循环变量,分别接收编号和元素的值
a = 'abcde'
for index,value in enumerate(a)
print(index,value)
# sorted:for 循环变量的时候,默认先遍历序列中较小的值,后遍历序列中较大的值
# 可迭代对象中的元素,需要是可排序的同类数据
a = [1,5,4,2]
# 从小到大打印
for i in sorted(a)
print(i)
# 从大到小打印
for i in sorted(a,reverse = True)
print(i)
# reversed:将可迭代对象中的元素,从尾到头进行遍历
a = [1,5,4,2]
for i in reversed(a)
print(i)
# zip:同时遍历可迭代对象中同一序号元素
# 如果元素长度不一致,只遍历到最短的序列长度
x = [1,2]
y = [3,4]
z = [5,6,7]
for a,b,c in zip(x,y,z)
print(a,b,c)
- while 循环 语法:
while <条件>:
<语句1>
else:
<语句2>
# while 循环体内必须得存在更改条件的语句,否则很容易进入死循环
a = 1
while a<10:
print(a)
a += 1
else:
print('执行结束')
2.15 猜数字游戏
import random
random_num = random.randint(0,9)
times = 3
while times>0:
guess_num = int(input('请输入0-9整数:'))
if guess_num>random_num:
print('大了')
elif guess_num<random_num:
print('小了')
else:
print('恭喜你猜中啦,正确答案是:'+str(random_num))
break
times -= 1
if times == 0:
print('你三次都没有猜中,正确答案是:'+str(random_num))
2.16 函数的使用
print('lemon','pear',seq=',',end='*')
2 ** 3 # 2的3次方
# 等价于
pow(2,3)
函数的基本形式:
def <函数名> (参数):
<函数语句>
return <返回值>
# def:声明一个函数
# 函数名:不要定义为 Python 关键字,不要与 Python 内置函数同名
# 函数参数
# 默认两个空格缩进的函数语句,表示属于该函数
# return 后可以没有返回值,也可以省略return语句
# return 后没有返回值或不写return语句,默认返回 None
# 查询 Python 关键之: help('keywords')
# 查询 Python 内置函数: dir(__builtins__)
# 关于函数的参数:
# 参数类型有:必须参数 、 可变参数 、 默认值参数 、 可变关键字参数
def func_name(param1,*args,param2=0,**kwargs):
pass
# param1:必须参数,定义了多少个参数,就必须得传递多少个参数
# *args:可变参数,可以传递任意个参数
# param2:默认值参数,给参数赋默认值
# **kwargs:可变关键字参数,可以传递任意个关键字参数
# 参数使用顺序: 必须参数 可变参数 默认值参数 关键字可变参数
参数:
def details(apple,lemon):
print('apple的数量:'+apple)
print('lemon的数量:'+lemon)
details(3,4)
details(lemon=8,apple=10)
# 关键字参数:增强代码可读性,不需要强制记忆参数顺序,可任意调换参数传递的顺序
def message(name,age,sex='male',nationality='China'):
print('姓名:' + str(name))
print('年龄:' + str(age) + '岁')
print('性别:' + str(sex))
print('国籍:' + str(nationality))
# 默认值参数:如果需要修改默认值参数,建议使用关键字参数,对默认值参数进行重新赋值。关键字参数可以不遵循默认值顺序
message('lemon',18)
message('Alice',22,sex='female',nationality='USA')
# 序列解包:将序列中的元素平铺出来,按照顺序分别赋值给多个变量
# 序列:字符串、列表、元组
s = '123'
a,b,c = s
print('a的值为:' + str(a) + ' 类型为:' + str(type(a)))
print('a的值为:' + str(b) + ' 类型为:' + str(type(b)))
print('a的值为:' + str(c) + ' 类型为:' + str(type(c)))
# 赋值的变量数量,需要与序列中的元素数量一致
# 可变参数:可以传递任意个参数,这些参数在函数调用时自动组装为一个 tuple
def func_args(*args):
print(args)
print(type(args))
func_args() # 打印的args为:() , 打印的type(args)为:<class 'tuple'>
func_args(1,2) # 打印的args为:(1,2) , 打印的type(args)为:<class 'tuple'>
a = (1,2)
func_args(a) # 打印的args为:((1,2),) , 打印的type(args)为:<class 'tuple'>
func_args(*a) # 打印的args为:(1,2) , 打印的type(args)为:<class 'tuple'>
# * 星号的作用是将元组里面的元素平铺出来,传递到可变参数的函数里面
# 如果想将一个序列内的元素平铺出来,传递到可变参数的函数里面,可使用序列解包操作
# 可变参数:可以传递任意个参数,也可传递一个序列,序列前面需要加上一个 *
def add_all(*args):
sum = 0
for i in args:
sum += i
return sum
# 可变关键字参数:可传递任意个关键字参数,这些关键字参数在函数调用的时候会自动组装为一个 dict
def func_kwargs(**kwargs):
print(kwargs)
print(type(kwargs))
func_kwargs() # 打印的kwargs为:{} , 打印的type(kwargs)为:<class 'dict'>
func_kwargs(lemon=5,apple=10) # 打印的kwargs为:{'lemon':5,'apple':10} , 打印的type(kwargs)为:<class 'dict'>
fruits = {'pear':5,'banana':6}
func_kwargs(fruits) # 报错
func_kwargs(**fruits) # 打印的kwargs为:{'pear':5,'banana':6} , 打印的type(kwargs)为:<class 'dict'>
2.17 作用域
Python 作用域:
- L (Local) 局部作用域
- E (Enclosing) 嵌套函数外层非全局作用域
- G (Global) 全局作用域
- B (Built-in) 内建作用域
变量:全局变量、局部变量
Python 没有块级作用域
if 5>0:
lemon = 5
print(lemon) # 5
for i in range(10):
lemon = 9
print(lemon) # 9
i = 1
while i<3:
lemon = 3
i += 1
print(lemon) # 3
作用域链:具有链式查找特性
- 特点:
- 函数内部引用变量,会优先引用最近局部变量
- 函数内部引用变量,会逐级向上寻找
global关键字:
def fruit():
lemon = 5
fruit()
print(lemon) # 报错
def fruit():
global lemon,pear # 使用 global 关键字,可声明改变量为全局变量
lemon = 5
pear = 10
fruit()
print(lemon,pear) # 5 10
banana = 5
def fruit():
banana = 10
print('函数内部的banana为:' + str(banana))
fruit()
print('全局的banana为:' + str(banana))
# 打印结果为:
# 函数内部的banana为:10
# 全局的banana为:5
# 使用 global 关键字给全局变量重新赋值
banana = 5
def fruit():
global banana
banana = 10
print('函数内部的banana为:' + str(banana))
fruit()
print('全局的banana为:' + str(banana))
# 打印结果为:
# 函数内部的banana为:10
# 全局的banana为:10
程序运行第一个 return 语句后,大多数情况下会跳出该函数,不再执行之后代码
# try excepy finally
# return 返回多个结果
def fruit(lemon,apple):
lemon = lemon * 2
apple = apple * 2
return lemon,apple
2.18 斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列:
1,1,2,3,5,8,13,21,34,……
这个数列从第三项开始,每一项都等于前两项之和
在数学上的递推方法:
F(1)=1
F(2)=1
F(n)=F(n-1)+F(n-2) (n>=3,n∈N*)
# 实现:用户输入任意数字,返回第N项数字
def fib(num):
if num <= 0:
raise Exception('数字要大于0') # 中断函数
if num == 1 or num == 2:
return 1
return fib(num-1) + fib(num-2)
将第一项到第N项结果存为一个列表:
# 列表推导式
# [循环变量名 for 循环变量名 in 可迭代对象 if 条件判断]
a = []
for i in range(10):
a.append(i)
a # [0,1,2,3,4,5,6,7,8,9]
b = [i for i in range(10)]
b # [0,1,2,3,4,5,6,7,8,9]
b = [i for i in range(10) if i>5]
b # [6,7,8,9]
num = int(input('请输入数字:'))
fibs_list = [fib(i) for i in range(1,num+1)]
fibs_list #
2.19 面向对象
- 面向过程:核心是在过程二字,面向过程设计思维,就好比精心设计好一条流水线,考虑周全,相应时候处理相应问题。
- 优点:将复杂的问题流程化,进而简单化
- 缺陷:扩展性差(如果更改需求,可能整个代码都需要重写,牵一发而动全身)
面向过程适用一些简单的、固定的、不需要更新迭代的问题,如果任务复杂,且需要不断更新迭代和维护的,推荐使用面向对象。
面向过程:
def test(x,y):
if x > y:
return x
elif x < y:
return y
return x + y
- 面向对象:对真实世界的模拟
面向对象编程特点:
- 可以编写表示真实世界中的事物和情景的类,并基于这些类来创建对象
- 可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率
面向对象三大特点:
- 封装性: 将对象的特征与行为保存起来
- 继承性: 通过继承,子类可快速获取父类特征与行为
- 多态性: 不同的子类对象,调用相同的父类方法,产生不同的执行结果
2.20 类
类:描述具有相同的特征和行为的对象的集合
- 通过变量可以刻画类的特征
- 通过方法可以描述类的行为
注意:类可以去定义,但不负责去执行相关方法
语法:
class 类名():
变量 # 刻画类的特征
# 实例方法
def 相关方法名(self,相关参数): # 描述类的行为
pass
# 类方法
@classmethod
def 方法名(cls,相关参数)
print('')
# 静态方法
@staticmethod
def 方法名(相关参数)
print('')
# 关于 self
# self 名称是约定成俗的
# self 指向的是类实例化后的对象本身
# self 只有在类的方法中才会有,函数是不必带有 self 的
# self 在定义类的方法(实例方法)时是必须有的
# self 在调用时不必传入相应的参数
# 通过 @classmethod 声明一个类方法
# 静态方法:与普通函数基本上没有什么区别
# 静态方法与类、对象没有太大关系的时候,可以使用该方法
# 通过 @staticmethod 声明一个静态方法
# 成员可见性:
# public 公开性 (外部可以访问相关变量,或 外部可以调用相关方法)
# private 私有性 (外部不可以访问相关变量,或 外部不可以调用相关方法)
class Men():
gender = 'male'
avg_height = 1.7
def __init__(self,name,age):
# 初始化对象特征
print('这是构造函数 __init__')
self.name = name
self.age = age
self.__testAge = age # 私有变量:在变量前面添加两个下划线
self.salary = 0
def think(self):
print('thinking')
def __testThink(self): # 私有方法:在方法前面添加两个下划线
print('thinking')
def sleep(self):
print('sleeping')
def modify_salary(self,salary):
self.salary = salary
@classmethod
def modify_height(cls,height):
cls.avg_height += height # 修改类变量
print('Success.Now the avg_height is ' + str(cls.avg_height))
# classmethod 类方法
# cls 是区别于示例方法的 self
@staticmethod
def plus_num(x,y):
return x + y
men = Men('lemon',18) # 类实例化,生成一个对象
men.sleep()
men.think()
men.name # lemon
men.__dict__ # {'name':'lemon','age':18}
men.avg_height = 1.75 # 这样修改的不是 Men 类中的 avg_height,而是相当于在类中 __init__ 创建了一个 self.avg_height = 1.75
Men.modify_height(0.05)
Men.__dict__
men.plus_num(2,3) # 6
men.__testAge # 报错
men.testAge # 报错
men._Men__testAge # 私有变量可以通过这种方式获取
men.__testThink # 报错
men.testThink # 报错
men._Men__testThink # 私有方法可以通过这种方式调用
men.salary = 10 # 不建议这样直接修改实例变量的值,建议通过定义方法来修改实例变量的值
men.modify_salary(20)
构造函数:可以让模板生成不同特征的对象
继承:子类可以直接使用父类的功能,减少重复代码
super关键字:不仅可以调用父类的构造函数,也可调用父类实例方法
class Men(): # 父类 或 几类
gender = 'male'
avg_height = 1.7
def __init__(self,name,age):
self.name = name
self.age = age
def sleep(self):
print('sleeping')
def think(self):
print('thinking')
class ChineseMen(Men): # 子类
def __init__(self,name,age,height):
# self.name = name
# self.age = age
# 上面两行可以改为下面这一行
# Men.__init__(self,name,age)
# 上面一行可以改为下面这一行
super(ChineseMen,self).__init__(name,age)
self.height = height
def sleep(self):
# Men.sleep(self)
# 上面一行可以改为下面这一行
super(ChineseMen,self).sleep()
print(self.name + 'is sleeping')
xiaoming = ChineseMen('xiaoming', 18, 180)
xiaoming.__dict__ # {'name':'xiaoming','age':18,'height':180}
2.21 正则表达式
import re
re.findall(pattern, string, flags) # 搜索整个字符串,返回所有匹配项
re.match(pattern, string, flags) # 从字符串首字符开始匹配,若首字符不匹配,则返回None,若匹配则返回第一个匹配对象
re.search(pattern, string, flags) # 搜索整个字符串,若全都不匹配,则返回None,若匹配则返回第一个匹配对象
# pattern 正则表达式匹配规则
# string 要进行匹配的字符串
# flags 可选参数,进行特定条件的匹配
re.sub(pattern, repl, string, count=0, flags=0) # 正则替换
# pattern 正则表达式
# repl 要替换的内容,也可以传入函数
# string 被替换的字符串
# count 默认为0,代表全部替换,1代表替换1次,2代表替换2次
match_str = 'lemon&apple&lemoon&banana&lemooon&pear&lemoooon'
re.findall('lemon',match_str) # ['lemon']
re.findall('lemo{1,4}n',match_str) # ['lemon','lemoon','lem0ooon','lemoooon']
match_str = 'bac | bbc | bcc | bdc | bec'
re.findall('b[ab]c',match_str) # ['bac','bbc']
re.findall('b[^ab]c',match_str) # ['bcc','bdc','bec']
re.findall('b[abcd]c',match_str) # ['bac','bbc','bcc','bdc']
re.findall('b[a-d]c',match_str) # ['bac','bbc','bcc','bdc']
re.findall('b[^a-d]c',match_str) # ['bec']
# \d 匹配一个数字字符
# \D 匹配一个非数字字符
match_str = '&a0b12c344d55&AC_'
re.findall('\d',match_str)
re.findall('\d{1,}',match_str)
re.findall('\D',match_str)
# \w 匹配一个包括下划线的单词字符
# \W 匹配一个非包括下划线的单词字符
re.findall('\w',match_str)
re.findall('\W',match_str)
# \s 匹配一个空白字符 如空格、制表符、换页符等
# \S 匹配一个非空白字符
match_str = '\r\t&a0b12c344d55&AC_ \n'
re.findall('\s',match_str)
re.findall('\S',match_str)
# 贪婪匹配
# 贪婪 倾向于最大长度匹配
# 非贪婪 倾向于最小长度匹配
match_str = 'lemon12banana34pear56'
re.findall('[a-z]{4,6}',match_str) # ['lemon','banana','pear']
re.findall('[a-z]{4,6}?',match_str) # ['lemo','bana','pear']
# 匹配次数
# * 代表匹配前面的字符零次或多次 {0,}
# + 代表匹配前面的字符一次或多次 {1,}
# ? 代表匹配前面的字符零次或一次 {0,1}
# 对于 ? 总结:
# 1. 如果数量词后面有 ?,该 ? 代表非贪婪的关键字,倾向于取最小长度匹配
# 2. 如果字符后面有 ?,该 ? 代表匹配前面字符 0次或1次
match_str = 'abcdef 123456 abcdef 456 abc'
re.findall('[a-z]{3,6}',match_str) # ['abcdef','abcdef','abc']
# 定位符
# ^ 匹配字符串开始的位置
# $ 匹配字符串结束的位置
re.findall('^[a-z]{6}',match_str) # ['abcdef']
re.findall('[a-z]{3}$',match_str) # ['abc']
# 组的匹配
match_str = 'lemonlemonlemonappleapplepearpear'
re.findall('(lemon){3}',match_str) # ['lemon']
re.search('(lemon){3}',match_str) # <_sre.SRE_Matvh object; span(0,15),match='lemonlemonlemon'>
# 组 与 字符集 的区别
# (lemon) 匹配 lemon 这一组字符
# [lemon] 匹配 括号中的任意一个字母
# flags可选参数
match_str = 'lemon LEMON'
re.findall('lemon',match_str,re.I) # ['lemon','LEMON']
# . 匹配除 “\n” 之外的任何单个字符
match_str = '\n123 abc\r'
re.findall('.',match_str,re.S) # 使用 re.S 可以让 . 也匹配 \n
match_str = 'lemon\n LEMON\n'
re.findall('lemon.',match_str,re.I | re.S) # ['lemon\n', 'LEMON\n']
# match search
match_str = 'a5678 lemon 1234'
re.findall('\d',match_str) # ['5','6','7','8','1','2','3','4']
re.match('\d','5678 lemon 1234') # <_sre.SRE_Match object; span=(0,1),match='5'>
re.search('\d',match_str) # <_sre.SRE_Match object; span=(0,1),match='5'>
r = re.search('\d',match_str) # <_sre.SRE_Match object; span=(0,1),match='5'>
r.group() # '5'
# group 组的匹配
# match_str = 'lemonlemonlemonappleapplepearpear'
match_str = 'life is mostly happy,but sometimes sad'
# is mostly cheerful,but sometimes
# is mostly cheerful sometimes sad
r = re.search('life(.*)sad',match_str)
r # <_sre.SRE_Match object; span=(0,38),match='life is mostly happy,but sometimes sad'>
r.group(0) # life is mostly happy,but sometimes sad
r.group(1) # is mostly happy,but sometimes
r1 = re.search('left(.*)but(.*)sad',match_str)
r1 # <_sre.SRE_Match object; span=(0,38),match='life is mostly happy,but sometimes sad'>
r1.group(1) # is mostly happy,
r1.group(2) # sometimes
r1.group() # (' is mostly happy,',' sometimes ')
# 正则替换
match_str = 'lemon apple 123456789 lemon lemon'
re.sub('lemon','a',match_str,count=0) # 'a apple 123456789 a lemaon'
re.sub('lemon','a',match_str,count=1) # 'a apple 123456789 lemon lemon'
re.sub('lemon','a',match_str,count=2) # 'a apple 123456789 a lemon'
# 需求:数字小于 7 的,都转为 0,数字大于等于 7 的,都转为 10
def tranform(value):
pass # pass为站位操作
re.sub('\d',tranform,match_str,count=0) # 'lemon apple lemon lemon'
def tranform(value):
print(value)
re.sub('\d',tranform,match_str,count=0)
# <_sre.SRE_Match object; span=(12,13),match='1'>
# <_sre.SRE_Match object; span=(13,14),match='2'>
# <_sre.SRE_Match object; span=(14,15),match='3'>
# <_sre.SRE_Match object; span=(15,16),match='4'>
# <_sre.SRE_Match object; span=(16,17),match='5'>
# <_sre.SRE_Match object; span=(17,18),match='6'>
# <_sre.SRE_Match object; span=(18,19),match='7'>
# <_sre.SRE_Match object; span=(19,20),match='8'>
# <_sre.SRE_Match object; span=(20,21),match='9'>
def tranform(value):
match_num = value.group()
print(match_num)
if int(match_num) < 7:
return '0'
return '10'
re.sub('\d',tranform,match_str,count=0) # 'lemon apple 000000101010 lemon lemon'
正则表达式全集:
| 字符 | 描述 |
|---|---|
| \ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。串行“\”匹配“\”而“(”则匹配“(”。 |
| 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。 | |
| $ | 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。 |
| * | 匹配前面的子表达式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}。 |
| + | 匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。 |
| ? | 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。 |
| {n} | n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。 |
| {n,} | n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。 |
| {n,m} | m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。 |
| ? | 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。 |
| . | 匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。 |
| (pattern) | 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用9属性。要匹配圆括号字符,请使用“(”或“)”。 |
| (?:pattern) | 匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。 |
| (?=pattern) | 正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
| (?!pattern) | 正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始 |
| (?<=pattern) | 反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。 |
| (?<!pattern) | 反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。 |
| x|y | 匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。 |
| [xyz] | 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。 |
| [^xyz] | 负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“p”。 |
| [a-z] | 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。 |
| [^a-z] | 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。 |
| \b | 匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。 |
| \B | 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。 |
| \cx | 匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。 |
| \d | 匹配一个数字字符。等价于[0-9]。 |
| \D | 匹配一个非数字字符。等价于[^0-9]。 |
| \f | 匹配一个换页符。等价于\x0c和\cL。 |
| \n | 匹配一个换行符。等价于\x0a和\cJ。 |
| \r | 匹配一个回车符。等价于\x0d和\cM。 |
| \s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。 |
| \S | 匹配任何非空白字符。等价于[^ \f\n\r\t\v]。 |
| \t | 匹配一个制表符。等价于\x09和\cI。 |
| \v | 匹配一个垂直制表符。等价于\x0b和\cK。 |
| \w | 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]” |
| \W | 匹配任何非单词字符。等价于“[^A-Za-z0-9_]” |
| \xn | 匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。. |
| \num | 匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。 |
| \n | 标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。 |
| \nm | 标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。 |
| \nml | 如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。 |
| \un | 匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。 |
常用正则表达式
| 字符 | 描述 |
|---|---|
| 用户名 | /^[a-z0-9_-]{3,16}$/ |
| 密码 | /^[a-z0-9_-]{6,18}$/ |
| 十六进制值 | /^#?([a-f0-9]{6}|[a-f0-9]{3})$/ |
| 电子邮箱 | /^([a-z0-9_.-]+)@([\da-z.-]+).([a-z.]{2,6})/ |
| URL | /^(https?://)?([\da-z.-]+).([a-z.]{2,6})([/\w .-])/?$/ |
| IP 地址 | /((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/ 或者 /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ |
| HTML 标签 | /^<([a-z]+)([^<]+)(?:>(.)</\1>|\s+/>)$/ |
| 删除代码\注释 | (?<!http:|\S)//.*$ |
| Unicode编码中的汉字范围 | /^[\u2E80-\u9FFF]+$/ |
2.22 Pycharm
官网地址:www.jetbrains.com/pycharm/
download:
- 运行 Pycharm 需要绑定 Python 解释器
- 找到 Python 的安装路径,如:D:\tools\python\python.exe
- 打开 PyCharm =》 打开项目 =》 File =》 Setting =》 Project: =》 Python Interpreter (Python解释器) =》 将Python的安装路径添加进去即可
2.23 Python 模块
-
基本组织结构
包(文件夹) =》 模块(文件) =》 变量、for循环、while循环、def、class
创建一个包:打开项目 =》 右键 =》 New =》 Python Package =》 例如:libs =》 会生成一个 libs文件夹,在libs文件夹下面会生成一个 init.py ,init.py 声明了 libs 是一个包,如果没有 init.py 则说明 libs 只是一个文件夹不是一个包。
在包里面可以创建很多模块,例如在 libs 下创建:p1.py、p2.py
- import 导入模块
p1.py、p2.py 两个模块在同一个包下面,根文件夹:右键 =》 Mark Directory as =》 Source Root libs/p1.py:
a = 1
b = 2
c = 3
libs/p2.py:
import p1
# import 模块名
print(p1.a,p1.b,p1.c)
# 也可以给p1取个别名: import p1 as t
# print(t.a,t.b,t.c)
跨包访问:
main.py:
import libs.p1 as t
print(p1.a)
print(p1.b)
print(p1.c)
- from import libs/p2.py:
from p1 import a,b,c
# from p1 import *
print(a)
print(b)
print(c)
main.py:
from libs.p1 import *
print(a)
print(b)
print(c)
设置哪些可以导入哪些不可以导入:
libs/p1.py:
__all__ = ['a','b'] # 这样在其他模块中就不能导入 c 了,只能导入 a、b
a = 1
b = 2
c = 3
- init.py
- 声明一个文件夹为一个包
- import 包 实际上导入的是这个包下面的 init.py
- 该模块名为一个包名
- 自定义选择哪些模块可以导入
libs/init.py:
print('This is libs.__init__.py')
print(__name__) # libs
__all__ = ['p1'] # 自定义 libs 包下的p1模块可以呗导入,其他如p2不可被导入
main.py
import lib # 导入的是 libs 下的 __init__.py
from libs import p1
libs/init.py:
__all__ = ['p1'] # 自定义 libs 包下的p1模块可以呗导入,其他如p2不可被导入
main.py
from libs import *
print(p1.a)
print(p2.a) # 报错
- name libs/init.py:
print(__name__)
libs/p1.py:
def add(x,y):
sum = x + y
print(sum)
return sum
# 只有从当前模块去运行才会执行,如果在其他模块导入当前模块则不执行
if __name__ == '__main__':
add(3,4)
main.py
from libs.p1 import add
add(5,5)
2.24 迭代器、生成器、装饰器
- 迭代器
- 迭代器:可以理解为一个容器,每次从容器中取出一个数据,直到数据被取完为止
- 自定义迭代器:
- 以类为例:需要在类中,实现两个方法 iter 与 next
其中:
- iter 方法需要返回对象本身,它是for循环使用迭代器的要求;
- next 方法用于返回容器中下一个元素,当容器中的数据取完时,需要引发 StopIteration 异常。
- 以类为例:需要在类中,实现两个方法 iter 与 next
其中:
# 需求:
# 1. 自定义迭代器,通过传入最小值最大值,返回该范围所有数值的3次方
# 2. 将返回的值,存入 num_list 列表中
class Number():
def __init__(self,min,max):
self.min = min
self.max = max
def __iter__(self):
return self
def __next__(self):
# 返回这个范围内所有数值的3次方
num = self.min
if self.min <= self.max:
self.min += 1
return num **3
else:
raise StopIteration
for i in Number(1,5):
print(i)
num_list = []
for i in Number(1,5):
num_list.append(i)
num_list # [1,8,27,64,125]
- 生成器
如果一个列表中,存有海量的数据,如果仅仅只是想访问其中某几个元素,那么这样的操作户特别耗内存;
- 生成器特点:操作海量数据,节约大量内存空间
- 生成器创建:
- 函数中如果包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个生成器(generator)对象。
- 在 Python 中,使用了 yield 的函数被称为生成器(generator)。
- 运行特点:
- 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
- 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值,并在下一次执行 next() 方法时从当前位置继续运行。
# 创建一个生成器,掺入最大值最小值,执行 next() 方法
# 生成器一般都是跟函数搭配的
def mygene(min,max):
while min < max:
yield min
min += 1
my_gene = mygene(1,5)
next(my_gene)
next(my_gene)
next(my_gene)
# yield 与 return 区别:
# return后,会跳出当前函数,yield 不会跳出当前函数
# yield 保存当前函数的执行状态,在返回后,函数又回到之前保存的状态继续执行。
def test():
return 1
return 2
def genetest():
yield 1
yield 2
test = genetest()
next(test)
next(test)
- 闭包
# 闭包特点:(必需满足以下3个条件才是闭包函数)
# 1. 函数内部,再定义函数
# 2. 内部函数引用了外部变量但非全局变量
# 3. 需要把内部函数返回
def outer():
a = 0
def inner(b):
print(a+b)
return inner
f = outer()
f.__closure__[0].cell_contents # 返回0; 返回 a 的值,则说明是闭包函数,否则不是闭包函数
def outer():
a = 0
def inner(b):
print('')
return inner
f = outer()
f.__closure__[0].cell_contents # 报错,因为 内部函数并没有引用外部函数变量
# 如何修改闭包函数变量 a 的值
def outer():
a = 0
def inner(b):
nonlocal a # nonlocal 可以声明 a 不是当前函数的变量,而是上一级函数的变量
a +=b
return inner
f = outer()
f(10)
f.__closure__[0].cell_contents # 10
f(30)
f.__closure__[0].cell_contents # 40
# 闭包作用:
# 1. 定制装饰器
# 2. 并行运算
# ...
- 装饰器
装饰器是一种增加函数或类功能的简单方法,它可以快速地给不同的函数或类传入相同的功能。
调用被装饰的函数,与之前的调用过程没有任何的区别
def func():
print('hello func')
def func1():
print('hello func1')
# 需求:
# 给上面函数,加上两句打印
# print('开始执行')
# print('结束执行')
# 下面这种写法可以实现,但是效率低
def func():
print('开始执行')
print('hello func')
print('结束执行')
# 装饰器基本格式
def decorate(func): # 定义装饰器函数,参数为func,代表被装饰的函数,装饰器函数的名字可以自定义,不一定叫decorate,也可以命名为abc
def wrapper(*args,**kwargs): # 新定义一个包装函数,用于返回;名字可以自定义,不一定要命名为 wrapper
print('执行开始')
func(*args,**kwargs) # 调用被装饰的函数
print('执行结束')
return wrapper # 返回包装函数
# 使用
@decorate
def func():
print('hello func')
func()
# 打印结果:
# 执行开始
# hello func
# 执行结束
@decorate
def func1():
print('hello func1')
func1()
# 打印结果:
# 执行开始
# hello func1
# 执行结束
2.25 Python常见高级用法
- Lambda 匿名函数
# 匿名函数:没有定义函数的名称,可以实现函数某些简单功能
# 语法
lambda param_list:expression
# param_list:参数列表
# expression:建议书写一些简单的表达式,没法完整实现复杂代码块内容
# 需求
# 传入 x,y
# 返回 x+y 的值
f = lambda x,y:x+y # 如果 x+y 改为 a=x+y 则会报错
f(3,4) # 7
# 需求:
# 传入两个参数 x,y ,如果 x>=y 返回 x+y
# 如果 x < y , 返回 x-y
# 普通函数实现:
def f(x,y):
if x>=y:
return x+y
return x-y
# 匿名函数与三元表达式搭配实现
f = lambda x,y: x+y if x>=y else x-y
f(3,4) # -1
f(5,4) # 9
- 三元表达式
# 三元表达式格式
# 条件为真的结果 if 条件判断 else 条件为假的结果
# 需求:
# 输入一个单词
# 如果是小写单词,则返回小写单词,否则都返回大写单词
f = lambda x: x if x.islower() else x.upper()
f('hello')
f('Hello')
- 高阶函数:map
# map 格式:
map(func, *iterables)
# func 代表可接收一个函数
# iterables 代表可接收一个或多个可迭代的序列
a = [1,2,3,4,5]
# 需求:
# 生成一个列表b,列表内的元素为a列表每个元素的三次方
b = []
for i in a:
b.append(i ** 3)
b # [1,8,27,64,125]
# 用map实现
def f(x):
return x ** 3
b = map(f,a)
b # <map at 0x1100eb1d0>
list(b) # [1,8,27,64,125]
# 用 map 和 lambda 实现
b = map(lambda x:x**3,a)
list(b) # [1,8,27,64,125]
# 需求:将两个列表元素相加之后结果,存放在一个新列表c中
a = [1,2,3,4,5]
b = [1,2,3,4,5]
c = map(lambda x,y:x+y,a,b)
list(c) # [2,4,6,8,10]
# 长度不一样时
a = [1,2,3]
b = [1,2,3,4,5]
c = map(lambda x,y:x+y,a,b)
list(c) # [2,4,6]
- reduce
# reduce 格式
from functools import reduce
reduce(function, sequence[, initial])
# function 接收一个函数
# sequence 接收一个可迭代序列
# initial 初始运算的值
a = [1,2,3,4,5]
# 需求:
# 计算a列表各元素相乘之后的值
num = reduce(lambda x,y:x*y,a) # x、y会在a中寻找,最开始x是1,y是2,相乘以后为2;然后x是2,y是3,相乘以后为6;然后x是6,y是4,相乘以后是24,以此类推
num # 120
num = reduce(lambda x,y:x*y,a,1000) # 1000*1*2
num # 120000
b = ['a','b','c']
r = reduce(lambda x,y:x+y,b)
r # 'abc'
r = reduce(lambda x,y:x+y,b,'???')
r # '???abc'
# 连续计算:计算a列表各元素相加之后的值
- filter
# filter 格式
filter(function, iterable)
# function 接收一个函数
# iterable 接收一个可迭代序列
# filter 返回结果必须是 True 或者 False
# 适用场景:用于序列元素过滤
a = [0,1,2,3,4,5]
# 需求:将 a列表中非0的元素,保存到b列表中
def f(x):
if x!=0:
return x
b = filter(f,a)
b # <fiter at 0x10d96d080>
list(b) # [1,2,3,4,5]
c = filter(lambda x:True if x!=0 else False,a)
list(c) # [1,2,3,4,5]
c = filter(lambda x:x,a)
list(c) # [1,2,3,4,5]
- 列表推导式
# 基本格式:
variable = [i for i in input_list if 条件判断] # for i in input_list 是for循环,for i in input_list 中的i是一个循环变量名,每次遍历可迭代序列然后添加第一个变量i,if条件判断会对第一个i进行筛选
# variable 列表名,可自定义
# i 循环变量名
# input_list 可迭代序列
# if 条件判断,如果不写的话,默认所有条件都成立
# 需求:如何快速生成一个 0-9 列表
a = [i for i in range(10)]
a # [0,1,2,3,4,5,6,7,8,9]
a = [i for i in range(10) if i>3]
a # [4,5,6,7,8,9]
# 需求:生成一个列表,列表内的元素为a列表每个元素的三次方
a = [1,2,3,4,5]
# map lambda
b = map(lambda x:x**3,a)
list(b) # [1,8,27,64,125]
c = [i**3 for i in a]
c # [1,8,27,64,125]
# 需求:将字典里面的键,保存到一个列表c中
d = {'lemon':5,'apple':3,'pear':4}
c = [i for i in d.keys()]
c # ['lemon','apple','pear']
# 扩展:将字典里的键与值,进行替换
e = {value:key for key,value in d.items()}
e # {5:'lemon',3:'apple',4:'pear'}
2.26 文件和异常
- 文件读取
- open函数
- open(file, mode='r',buffering=-1,encoding=None, errors=None, newline=None, closefd=True, opener=None)
- 参数说明:
- file:必需,文件路径(相对或绝对路径)
- mode:可选,文件打开模式
- encoding:一般使用utf-8
- buffering:设置缓冲
- errors:报错级别
- newline:区分换行符
- closefd:传入的file参数类型
- mode 常用参数:
- r : 以只读方式打开文件
- w : 以只写方式打开文件
- 如果改文件不存在,创建新文件
- 如果改文件已存在,则覆盖原文件
- a : 打开一个文件用于追加
- 如果改文件已存在,则在最尾处追加写入
- 如果改文件不存在,创建新文件进行写入
- 更多mode参数说明,可访问:www.runoob.com/python/file…
files/文本.txt
Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。
Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。
Python 是由 Guido van Rossum 在八十年代末和九十年代初,在荷兰国家数学和计算机科学研究所设计出来的。
Python 本身也是由诸多其他语言发展而来的,这包括 ABC、Modula-3、C、C++、Algol-68、SmallTalk、Unix shell 和其他的脚本语言等等。
像 Perl 语言一样,Python 源代码同样遵循 GPL(GNU General Public License)协议。
现在 Python 是由一个核心开发团队在维护,Guido van Rossum 仍然占据着至关重要的作用,指导其进展。
Python 2.7 被确定为最后一个 Python 2.x 版本,它除了支持 Python 2.x 语法外,还支持部分 Python 3.1 语法。
main.py
# 实现简单的文件读取操作
# 文件的路径也可以用相对路径:files/文本.txt
f = open('文本.txt 的绝对路径',mode='r',encoding='utf-8')
data = f.read()
print(data)
f.close() # 用open打开要用close将文件关闭
# 为避免忘记close文件,可以用一下方式读取文件
with open('files/文本.txt',mode='r',encoding='utf-8') as f: # 用变量f来接收
data = f.read()
print(data)
- 文件的读取格式
- with open(file='file_path',mode='r',encoding='utf-8') as f:
- data = f.read() # 返回整个文件数据,如果文件较大,不建议用这种方法
- data1 = f.readline() # 返回一行数据
- data2 = f.readlines() # 以列表格式,返回整个文件数据
- 文件的写入格式
- with open(file='file_path',mode='w',encoding='utf-8') as f:
- file.write(str) # 将字符串写入文件
- file.writeline(sequence) # 向文件写入一个序列字符串列表,如果需要换行则要自己加入换行符
- 文件的写入
with open('files/文本.txt',mode='w',encoding='utf-8') as f:
#f.write('hello lemon\n hello world')
f.writelines(['hello pycharm\n','hello apple\n','hello'])
with open('files/文本.txt',mode='a',encoding='utf-8') as f:
f.write('hello lemon\n hello world')
f.writelines(['hello pycharm\n','hello apple\n','hello'])
- JSON与文件读写
-
(1)JSON(JavaScript Object Notation)特点:
- 1)JSON 是一种轻量级的数据交换格式,易于人阅读和编写
- 2)JSON 具有通用性,支持几乎所有的语言
- 3)JSON 支持跨平台,支持 windows,Linux,Mac平台
-
(2)常用JSON函数
- 1)json.dumps 将 Python 对象编码成 JSON 字符串
- 2)json.loads 将 已编码的 JSON 字符串解码为 Python 对象
- 3)json.dump 将 JSON 字符串数据写进文件
- 4)json.load 读取 JSON 文件里面的数据
- 5)python
- {'python':1,'Java':2,'Hadoop':3}
- {"python":1,"Java":2,"Hadoop":3}
- 6)JSON
- '{"python":1,"Java":2,"Hadoop":3}'
-
(3)Python 与 JSON 类型转换
Python JSON dict object list, tuple array str string int, float number True true False false None null 第一列文本居中 第二列文本居右
import json
def f1():
'''
对Python对象进行操作
'''
# json.dumps
# 将 Python 对象编码成 JSON 字符串
p_list = [
{'lemon':True,'apple':6},
{'pear':6,'banana':False},
]
p_dict = {'python':1,'Java':2,'Hadoop':None}
json_list = json.dumps(p_list)
json_dict = json.dumps(p_dict)
# json.loads
# 将已编码的 JSON 字符串解码为 Python 对象
list1 = json.loads(json_list)
dict1 = json.loads(json_dict)
def f2():
'''
文件的读写
'''
# 写入JSON文件
p_dict = '{"python":1,"Java":2,"hadoop":null,"lemon":true,"banana":false}'
with open('files/json_test.json','w',encoding='utf-8') as f:
json.dump(p_dict,f)
# 读取JSON文件
with open('files/json_test.json','r',encoding='utf-8') as f:
data = json.load(f)
data1 = json.loads(data)
print(data)
print(data1)
if __name__ == '__main__':
f2()
- try-except-finally捕捉异常
- (1)什么是异常:
- 1)异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。
- 2)一般情况下,在Python无法正常处理程序时就会发生一个异常
- 3)异常是Python对象,表示一个错误
- 4)当Python脚本发生异常时我们需要捕获处理,否则程序会终止执行
- (2)捕获异常的基本格式
try: 语句一 # 检测语句一是否存在错误 except 异常名称: 语句二 # 若语句一存在错误,可以捕获错误 finally: 语句三 # 无论是否存在错误,都会执行finally内代码 - (3)常见异常名称
- BaseException: 所有异常错误
- Exception: 常规异常错误
- ZeroDivisionError: 除0异常错误
- ValueError: 值类型异常错误
- 更多异常错误,可查看:www.runoob.com/python/pyth…
exception_demo.py
def f(num):
try:
num / 0
except ZeroDivisionError as e:
print(e)
finally:
print('执行结束')
def f1(num):
try:
return int(num)
except ValueError as e:
print(e)
finally:
print('执行结束')
# 同时捕获多个异常
def f2(num):
try:
return int(num)
except ZeroDivisionError as e:
print(e)
except ValueError as e:
print(e)
finally:
print('执行结束')
# 同时捕获多个异常简写
def f3(num):
try:
return int(num)
except (ZeroDivisionError,ValueError) as e:
print(e)
finally:
print('执行结束')
def f4(num):
try:
return int(num)
except BaseException as e:
print(e)
finally:
print('执行结束')
if __name__ == '__main__':
# f(1)
f1(a)
- raise 与 asert
- (1)raise 抛出异常
- 除了使用 try-except-finally 格式来捕获异常
- 也可以通过 raise 显示的引发异常
- 一旦引发 raise 后面的异常,将终止程序运行
- (2)assert 断言
- assert 的异常参数,其实就是在断言表达式后添加字符串信息,用来解释断言并更好的知道是哪里出了问题
- 基本格式:
- assert expression [,arguments]
- 如果 bool_expression 为 False,则会抛出 arguments 这个自定义异常信息
- 如果 bool_expression 为 True,则不会抛出 arguments 这个自定义异常信息
# 需求1:
# 1. 传入一个参数,判断是否为整型类型,如果不是,则抛出异常,终止程序
# 2. 判断是否大于等于5,如果小于5,则抛出异常,终止程序
def f2(num):
# if not isinstance(num,int):
# raise Exception('该参数不是一个整型类型')
# if num < 5:
# raise Exception('该参数小于5')
assert isinstance(num,int),'该参数不是一个整型类型'
assert num>=5,'该参数小于5'
if __name__ == '__main__':
f2('a')
# 需求2:
# 传入若干个参数,判断参数个数如果小于等于5,则抛出异常,终止程序
def f3(*args):
# if len(args)<=5:
# raise Exception('参数个数小于等于5个')
assert len(args)>5,'该参数个数小于等于5'
if __name__ == '__main__':
f3(1,2,3,4,5)
2.27 虚拟环境
- 为什么要搭建虚拟环境
项目A需要运行在Python2环境下,项目B需要运行在Python3环境下。
项目A和项目B,使用同一个包,但是项目A需要使用该包的1.0版本,项目B需要使用该包的2.0版本
那么创建虚拟环境,可以解决包管理的问题
- 搭建虚拟环境
pip install pipenv
创建一个文件夹
pipenv --three 会使用当前系统的Python3创建环境
pipenv shell 激活虚拟环境
pipenv --py 显示Python解释器信息
exit 退出当前的虚拟环境
- pipenv 常见操作
(1)包下载
下载包之前,将国外下载源,更改为国内源
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
修改下载源在 Pipfile 文件中修改
pipenv install requests
pipenv install requests--2.21.0
(2)查看当前下载包情况
pip list
(3)查看当前包依赖情况
pipenv graph
(4)更新包
pipenv update requests # 更新requests
pipenv update # 更新所有包
(5)卸载包
pipenv uninstall requests # 卸载requests包
pipenv uninstall --all # 卸载全部包并从Pipfile中移除
(6)其他操作
pipenv check # 检查安全漏洞
2.28 简单爬虫实战
- HTML简单介绍
超文本标记语言(HyperText Markup Language),是网页制作必备的变成语言。
超文本,可以包含文字、图片、链接,甚至音乐、程序等元素
超文本标记语言的结构包括“头”部分(英语:Head)、和“主体”部分(英语:Body)
其中“头”部提供关于网页的信息,“主体”部分提供网页的具体内容
基本格式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
-
XPath获取数据 XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。
常用路径表达式:
表达式 描述 / 从根节点选取 // 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 @ 选取属性
files/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>这是一级标题</h1>
<h2>这是二级标题</h2>
<p>这是一段文字</p>
<img src="视频水印.png">
<div>
<ul>hello lemon</ul>
<ul>hello world</ul>
</div>
<h3>这是三级标题</h3>
<div id="list">
<p>python</p>
<p>Java</p>
<p class="Hadoop">Hadoop</p>
</div>
</body>
</html>
xpath_demo.py
from lxml.html import fromstring
# fromstring 可以将字符串类型转换为html格式
with open('files/index.html','r',encoding='utf-8') as f:
data = f.read()
print(data)
print(type(data)) # <class 'str'>
selector = fromstring(data)
print(type(selector)) # <class 'lxml.html.HtmlElement'>
h1 = selector.xpath('/html/body/h1/text()')[0]
h1 = selector.xpath('//h1/text()')[0]
p = selector.xpath('/html/body/p/text()')[0]
p = selector.xpath('//body/p/text()')[0]
div_ul = selector.xpath('//div/ul/text()')
div_p = selector.xpath('//div/p/text()')
div_p = selector.xpath('//div[@id="list"]/p/text()')
div_p = selector.xpath('//div[@id="list"]/p[last()]/text()')
div_p = selector.xpath('//div[@id="list"]/p[@class="Hadoop"]/text()')
- 爬虫原则
- (1)明确爬取的内容
- (2)分析网页结构,找到目标的标签
- (3)分析目标标签,获取目标数据
- (4)数据入库
- 简单爬虫实战
(1)明确爬取的内容
正在上映的电影
(2)分析网页结构,找到目标的标签
div[@id="nowplaying"]/div[@class="mod-bd"]/ul/li
(3)分析目标标签,获取目标数据
电影名称、电影评分、电影评分人数
电影时长、上映年份、地区、导演、主要演员
(4)数据入库
写入到json文件里面
- 断点调试
Mac: fn + f6 单步调试
fn + f8 跳到下一个断点
Window: f6 单步调试
f8 跳到下一个断点
import requests # requests 这个包的将目标网站拉取下来
from lxml.html import fromstring
import json
class SpiderDouban():
def __init__(self,url):
self.url = url
self.header = {
'Accept': '',
'Accept-Encoding': '',
'Accept-Language': '',
'Host': '',
'Referer': '',
'User-Agent': '',
'': '',
}
def get_data(self):
r = requests.get(url=self.url,headers=self.headers)
data = fromstring(r.text)
selector = data.xpath('//div[@id="nowplaying"]/div[@class="mod-bd"]/ul/li')
for i in selector:
title = i.xpath('@data-title')
score = i.xpath('@data-score')
votecount = i.xpath('@data-votecount')
duration = i.xpath('@data-duration')
ralease = i.xpath('@data-ralease')
region = i.xpath('@data-region')
director = i.xpath('@data-director')
actors = i.xpath('@data-actors')
print(title)
movie_data.append({
'title': title if title else '',
'score': score if score else '',
'votecount': votecount if votecount else '',
'duration': duration if duration else '',
'ralease': ralease if ralease else '',
'region': region if region else '',
'director': director if director else '',
'actors': actors if actors else '',
})
with open('files/movie_data.json','w',encoding='utf-8') as f:
json.dump(movie_data,f,indent=1,ensure_ascii=False)
if __name__ == '__main__':
s = SpiderDouban('https://movie.douban.com/...')
s.get_data()
3 Python 可深入的方向
爬虫工程师:
相关爬虫工具:Scrapy 爬虫框架、Selerium
反爬策略(ip代理池、随机更换 User-Agent、Cookie禁用、自动限速等方法)
数据库知识(如:Mysql Oracle 等)
Web开发工程师:
相关框架:Django Flask
前端知识:JavaScript CSS HTML
数据库知识
数据分析师:
初级数据分析:
数据库相关知识:Mysql Oracle MongoDB Redis
中高级数据分析:
Python 数据科学常见包:Numpy Pandas Matplotlib Scipy
统计学知识:线性代数
机器学习常见算法:线性回归法、梯度下降法、PCA、SW、决策树、随机森林等
大数据方向:
相关工具:Spark Hadoop
其他语言基础:Java SE
Linux 相关知识
人工智能方向:
相关框架:TensorFlow (一个完全开源的人工智能框架)、Keras
相关工具:Matplotlib 、 Numpy、TensorBoard
Linux 相关知识