Python
Pythonpython开发环境搭建Python 解释器下载Python解释器安装Python解释器安装IDE PyCharmPython基本语法注释的分类及语法变量标识符命名习惯数据类型输入输出输出输入数据类型转换运算符条件语句if 语法if...else语句多重判断if嵌套三目运算符循环whilebreak和continuewhile循环嵌套for循环循环配合else字符串定义下标切⽚查找修改判断列表查找增加删除修改复制列表的循环遍历列表嵌套元组定义查询集合创建集合增加删除字典创建字典增删查询遍历公共操作运算符公共方法容器类型转换推导式列表推导式带if的列表推导式多个for循环创建列表推导式字典推导式集合推导式函数函数基本使用函数进阶文件操作文件基本操作⽂件和⽂件夹的操作面向对象类和对象面向对象实现方法魔法方法继承私有权限⾯向对象三大特性类属性和实例属性类方法和静态方法异常模块和包python 应用网络爬虫
python开发环境搭建
Python 解释器
Python解释器作⽤:运⾏文件
Python解释器种类
- CPython,C语⾔开发的解释器[官⽅],应⽤⼴泛的解释器
- IPython,基于CPython的⼀种交互式解释器
- 其他解释器
- PyPy,基于Python语言开发的解释器
- Jython,运行在java平台的解释器,直接把Python代码编译成java字节码执行
- IronPython,运⾏在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码。
下载Python解释器
[单击上述链接] -- 查找⽬目标⽂文件:Windows x86-64 executable installer -- 单击即可下载。
安装Python解释器
注意安装时候将python解释器加到PATH变量
安装IDE PyCharm
PyCharm基本使用
打开PyCharm -- [Create New Project] -- 选择项⽬根⽬录和解释器版本 -- [Create],即可完成新建⼀一 个项⽬
Python基本语法
注释的分类及语法
注释分为两类:单⾏注释 和 多行注释。
- 单⾏注释
只能注释⼀行内容,语法如下:
# 注释内容
- 多⾏行行注释
- 可以注释多行内容,⼀般用在注释一段代码的情况, 语法如下
变量
变量量名 = 值
变量量名⾃自定义,要满⾜足标识符命名规则。
标识符
标识符命名规则是Python中定义各种名字的时候的统⼀规范,具体如下
- 由数字、字⺟、下划线组成
- 不能数字开头
- 不能使⽤用内置关键字
- 严格区分大小写
内置关键字
命名习惯
- 见名知义。
- ⼤大驼峰:即每个单词首字母都大写,例如: MyName 。
- 小驼峰:第⼆个(含)以后的单词⾸字⺟⼤写,例如: myName 。
- 下划线:例如: my_name 。
数据类型
image-20201204104740151
检测数据类型的⽅方法: type()
例:
输入输出
输出
输出:程序输出内容给⽤用户
格式化输出
所谓的格式化输出即按照⼀定的格式输出内容。
格式化符号
- %06d,表示输出的整数显示位数,不足以0补全,超出当前位数则原样输出
- %.2f,表示小数点后显示的小数位数
格式化字符串串除了了%s,还可以写为
f'{表达式}'
f-格式化字符串是Python3.6中新增的格式化方法,该⽅法更简单易读
转义字符
- \n :换⾏行行。
- \t :制表符,⼀个tab键(4个空格)的距离
在Python中,print(), 默认自带 end="\n" 这个换⾏结束符,所以导致每两个 print 直接会换行展示,⽤户可以按需求更改结束符
输入
在Python中,程序接收用户输入的数据的功能即是输入。
输入的特点
- 当程序执⾏到 input ,等待用户输入,输入完成之后才继续向下执行。
- 在Python中, input 接收⽤用户输入后,⼀般存储到变量,⽅便使⽤。
- 在Python中, input 会把接收到的任意⽤户输入的数据都当做字符串处理
数据类型转换
转换数据类型的函数
函数
说明
将x转换为一个整数
将x转换为⼀个浮点数
创建⼀个复数,real为实部,imag为虚部
将对象 x 转换为字符串
将对象 x 转换为表达式字符串
⽤来计算在字符串中的有效Python表达式,并返回一个对象
将序列 s 转换为一个元组
将序列 s 转换为一个列列表
将⼀个整数转换为一个Unicode字符
将⼀个字符转换为它的ASCII整数值
将⼀个整数转换为一个⼗六进制字符串
将⼀个整数转换为⼀个八进制字符串
将⼀个整数转换为⼀个⼆进制字符串
案例
运算符
- 算数运算符
- 赋值运算符
- 复合赋值运算符
- ⽐较运算符
- 逻辑运算符
算数运算符
混合运算优先级顺序: () ⾼高于 ** ⾼高于 * / // % ⾼高于 + -
赋值运算符
⽐较运算符
⽐较运算符也叫关系运算符, 通常⽤来判断
运 算 符
描述
实例
逻辑运算符
数字之间的逻辑运算
条件语句
if 语法
例
if...else语句
多重判断
例
age >= 18 and age <= 60可以化简为18 <= age <= 60
if嵌套
例
三目运算符
条件成⽴执⾏的表达式 if 条件 else 条件不成⽴执⾏的表达式
循环
while
例
break和continue
break和continue是循环中满⾜一定条件退出循环的两种不同⽅式。
while循环嵌套
99乘法表
for循环
循环配合else
循环可以和else配合使⽤,else下⽅缩进的代码指的是当循环正常结束之后要执⾏的代码。
循环break ,else代码不执行
循环中间有一次continue,else代码会执行
for 和 else 也是类似结果
字符串
定义
字符串是 Python 中最常⽤的数据类型。我们⼀般使⽤引号来创建字符串。创建字符串很简单,只要为变量分配⼀个值即可。
字符串单引号和双引号都可以
一对引号字符串
三引号字符串
三引号形式的字符串支持换⾏
下标
切⽚
切⽚是指对操作的对象截取其中⼀部分的操作。字符串、列表、元组都⽀持切⽚操作
语法:
序列[开始位置下标:结束位置下标:步长]
注意 :
- 不包含结束位置下标对应的数据, 正负整数均可;
- 步长是选取间隔,正负整数均可,默认步长为1
查找
所谓字符串查找方法即是查找子串在字符串中的位置或出现的次数。
find():检测某个⼦串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则返回-1。
语法:
字符串串序列列.find(⼦子串串, 开始位置下标, 结束位置下标)
注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。
index():检测某个子串是否包含在这个字符串中,如果在返回这个⼦串开始的位置下标,否则报异常
语法:
字符串序列.index(⼦串, 开始位置下标, 结束位置下标)
注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找修改
其他查询函数
- rfind(): 和find()功能相同,但查找⽅向为右侧开始。
- rindex():和index()功能相同,但查找⽅向为右侧开始。
- count():返回某个子串在字符串中出现的次数
修改
所谓修改字符串,指的就是通过函数的形式修改字符串中的数据
- replace():替换
- 1 语法 :
字符串序列.replace(旧⼦串, 新⼦串, 替换次数)
注意:替换次数如果查出⼦串出现次数,则替换次数为该⼦串出现次数
案例
注意:数据按照是否能直接修改分为可变类型和不可变类型两种。字符串类型的数据修改的时候不能改变原有字符串,属于不能直接修改数据的类型即是不可变类型
- split(): 按照指定字符分割字符串。
- 语法
字符串序列.split(分割字符, num)
- 注意:num表示的是分割字符出现的次数,即将来返回数据个数为num+1个
注意:如果分割字符是原有字符串中的⼦串,分割后则丢失该⼦串。
- join():⽤一个字符或⼦串合并字符串,即是将多个字符串合并为⼀个新的字符串。
- 语法:
字符或⼦串.join(多字符串组成的序列)
- 案例
list1 = ['a', 'bb', 'ccc', 'dddd'] print('_'.join(list1))# a_bb_ccc_dddd t1 = ('a', 'bb', 'ccc', 'dddd') print('...'.join(t1))# a...bb...ccc...dddd
- capitalize():将字符串第⼀个字符转换成⼤写。
mystr = "hello world and USA and UK and Python" print(mystr.capitalize()) # Hello world and usa and uk and python
注意:capitalize()函数转换后,只字符串第⼀个字符⼤写,其他的字符全都小写。
- title():将字符串每个单词⾸字⺟转换成大写
mystr = "hello world and USA and UK and Python" print(mystr.title()) # Hello World And Usa And Uk And Python
- lower():将字符串中⼤写转⼩写。
mystr = "hello world and USA and UK and Python" print(mystr.lower()) # hello world and usa and uk and python
- upper():将字符串中⼩写转⼤写
mystr = "hello world and USA and UK and Python" print(mystr.upper()) # HELLO WORLD AND USA AND UK AND PYTHON
- lstrip():删除字符串左侧空⽩字符。
mystr = " hello world and USA and UK and Python" print(mystr.lstrip()) # hello world and USA and UK and Python
- rstrip():删除字符串右侧空白字符。
mystr = "hello world and USA and UK and Python " print(mystr.rstrip()) # llo world and USA and UK and Python
- strip():删除字符串两侧空⽩字符。
mystr = " hello world and USA and UK and Python " print(mystr.strip()) # hello world and USA and UK and Python
- ljust():返回⼀个原字符串左对⻬,并使⽤指定字符(默认空格)填充至对应⻓度的新字符串
- 语法:
字符串序列.ljust(长度, 填充字符)
mystr = "hello" print(mystr.ljust(10, '1')) # hello11111
- rjust():返回⼀个原字符串右对⻬,并使用指定字符(默认空格)填充⾄对应⻓度的新字符串,语法和ljust()相同。
mystr = "hello" print(mystr.rjust(10, '1')) # 11111hello
- center():返回⼀个原字符串居中对⻬,并使⽤指定字符(默认空格)填充至对应⻓度的新字符串,语法和ljust()相同
mystr = "hello" print(mystr.center(10, '1')) # 11hello111
判断
所谓判断即是判断真假,返回的结果是布尔型数据类型:True 或 False
- startswith():检查字符串是否是以指定⼦串开头,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查。
- 语法:
字符串序列.startswith(⼦串, 开始位置下标, 结束位置下标)
- 案例
mystr = "hello world and USA and UK and Python " print(mystr.startswith("hello", 5, 20)) # False print(mystr.startswith("hello", 0, 5)) # True
- endswith():检查字符串是否是以指定⼦串结尾,是则返回True,否则返回False。如果设置开始和结束位置下标,则在指定范围内检查。
- 语法:
字符串序列.endswith(⼦串, 开始位置下标, 结束位置下标)
- 案例
mystr = "hello world and USA and UK and Python" print(mystr.endswith("Python", 5, 20)) # False print(mystr.endswith("Python")) # True
- isalpha():如果字符串⾄少有一个字符并且所有字符都是字⺟则返回 True, 否则返回 False
mystr1 = 'hello' mystr2 = 'hello123' print(mystr1.isalpha()) # True print(mystr2.isalpha()) # False
- isdigit():如果字符串只包含数字则返回 True 否则返回 False
mystr1 = 'hello123' mystr2 = '123' print(mystr1.isdigit()) # False print(mystr2.isdigit()) # True
- isalnum():如果字符串⾄少有一个字符并且所有字符都是字⺟或数字则返回 True,否则返回 False。
mystr1 = 'hello123' mystr2 = '123-' print(mystr1.isalnum()) # True print(mystr2.isalnum()) # False
- isspace():如果字符串中只包含空⽩,则返回 True,否则返回 False。
mystr1 = 'hello123' mystr2 = ' ' print(mystr1.isspace()) # False print(mystr2.isspace()) # True
列表
列表可以⼀次性存储多个数据,且可以为不同数据类型。
格式:
[数据1, 数据2, 数据3, 数据4......]
查找
- 按下标查询
- 查询函数
- index():返回指定数据所在位置的下标 。如果不存在则报错
- 语法:
列表序列.index(数据, 开始位置下标, 结束位置下标)
- count():统计指定数据在当前列表中出现的次数。
- len():访问列表长度,即列表中数据的个数。
- 判断是否存在
- in:判断指定数据在某个列表序列,如果在返回True,否则返回False
name_list = ['Tom', 'Lily', 'Rose'] # 结果:True print('Lily' in name_list) # 结果:False print('Lilys' in name_list)
- not in:判断指定数据不在某个列表序列,如果不在返回True,否则返回False
name_list = ['Tom', 'Lily', 'Rose'] # 结果:False print('Lily' not in name_list) # 结果:True print('Lilys' not in name_list)
增加
作⽤:增加指定数据到列表中。
- append():列表结尾追加数据。
- 语法:
列表序列.append(数据)
name_list = ['Tom', 'Lily', 'Rose'] name_list.append('xiaoming') # 结果:['Tom', 'Lily', 'Rose', 'xiaoming'] print(name_list)
列表追加数据的时候,直接在原列表⾥⾯追加了指定数据,即修改了原列表,故列表为可变类型数据。
如果append()追加的数据是⼀个序列,则追加整个序列到列表
- extend():列表结尾追加数据,如果数据是⼀个序列,则将这个序列的数据逐⼀添加到列表
- 语法 :
列表序列.extend(数据)
- 单个数据
序列数据
- insert():指定位置新增数据。
- 语法:
列表序列.insert(位置下标, 数据)
name_list = ['Tom', 'Lily', 'Rose'] name_list.insert(1, 'xiaoming') # 结果:['Tom', 'xiaoming', 'Lily', 'Rose'] print(name_list)
删除
- del
- 语法:
del ⽬标
- 删除指定数据
删除列表
- pop():删除指定下标的数据(默认为最后⼀个),并返回该数据。
- 语法:
列表序列.pop(下标)
name_list = ['Tom', 'Lily', 'Rose'] del_name = name_list.pop(1) # 结果:Lily print(del_name) # 结果:['Tom', 'Rose'] print(name_list) name_list.pop() # ['Tom'] print(name_list)
- remove():移除列表中某个数据的第⼀个匹配项。
- 语法
name_list = ['Tom', 'Lily', 'Rose'] name_list.remove('Rose') # 结果:['Tom', 'Lily'] print(name_list)
- clear():清空列表
name_list = ['Tom', 'Lily', 'Rose'] name_list.clear() print(name_list) # 结果: []
修改
- 修改指定下标数据
name_list = ['Tom', 'Lily', 'Rose'] name_list[0] = 'aaa' # 结果:['aaa', 'Lily', 'Rose'] print(name_list)
- 逆置:reverse()
name_list = ['Tom', 'Lily', 'Rose'] name_list.reverse() print(name_list)# 结果:['Rose', 'Lily', 'Tom']
- 排序:sort()
- 语法:
列表序列.sort( key=None, reverse=False)
,排序的是列表里的具体数值 - 数字
字符串 按首字母排序
注意:reverse表示排序规则,reverse = True 降序, reverse = False 升序(默认)
复制
函数:copy()
列表的循环遍历
while
for
列表嵌套
所谓列表嵌套指的就是⼀个列表⾥⾯包含了其他的⼦列表。 应⽤场景:要存储班级⼀、二、三个班级学⽣姓名,且每个班级的学⽣姓名在⼀个列表。
元组
⼀个元组可以存储多个数据,元组内的数据是不能修改的。
定义
元组特点:定义元组使⽤小括号,且逗号隔开各个数据,数据可以是不同的数据类型。
如果定义的元组只有⼀个数据,那么这个数据后⾯也添加逗号,否则数据类型为唯⼀的这个数据的数据类型
查询
- 按下标查找数据
tuple1 = ('aa', 'bb', 'cc', 'bb') print(tuple1.index('aa')) # 0
- index():查找某个数据,如果数据存在返回对应的下标,否则报错,语法和列表、字符串的index ⽅法相同
tuple1 = ('aa', 'bb', 'cc', 'bb') print(tuple1.index('aa')) # 0
- count():统计某个数据在当前元组出现的次数。
tuple1 = ('aa', 'bb', 'cc', 'bb') print(tuple1.count('bb')) # 2
- len():统计元组中数据的个数。
tuple1 = ('aa', 'bb', 'cc', 'bb') print(len(tuple1)) # 4
注意:元组内的直接数据如果修改则立即报错
但是如果元组⾥⾯有列表,修改列表⾥⾯的数据则是⽀持的,故自觉很重要。
集合
创建集合
创建集合使⽤ {} 或 set() , 但是如果要创建空集合只能使⽤set() ,因为 {} 用来创建空字典
- 集合可以去掉重复数据;
- 集合数据是⽆序的,故不⽀持下标
增加
- add()
s1 = {10, 20} s1.add(100) s1.add(10) print(s1) # {100, 10, 20}
因为集合有去重功能,所以,当向集合内追加的数据是当前集合已有数据的话,则不进⾏任何操作。
- update(), 追加的数据是序列
s1 = {10, 20} # s1.update(100) # 报错 s1.update([100, 200]) s1.update('abc') print(s1)
删除
- remove(),删除集合中的指定数据,如果数据不存在则报错。
s1 = {10, 20} s1.remove(10) print(s1) s1.remove(10) # 报错 print(s1)
- discard(),删除集合中的指定数据,如果数据不存在也不会报错。
s1 = {10, 20} s1.discard(10) print(s1) s1.discard(10) print(s1)
- pop(),随机删除集合中的某个数据,并返回这个数据。
- in:判断数据在集合序列
- not in:判断数据不在集合序列
字典
字典里⾯的数据是以键值对形式出现,字典数据和数据顺序没有关系,即字典不支持下标, 后期⽆论数据如何变化,只需要按照对应的键的名字查找数据即可
创建字典
语法
- 符号为大括号
- 数据为键值对形式出现
- 各个键值对之间用逗号隔开
注意:⼀般称冒号前⾯的为键(key),简称k;冒号后面的为值(value),简称v。
增
写法:字典序列[key] = 值
如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。
字典为可变类型。
删
- del() / del:删除字典或删除字典中指定键值对
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} del dict1['gender'] # 结果:{'name': 'Tom', 'age': 20} print(dict1)
- clear():清空字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} dict1.clear() print(dict1) # {}
查询
- key值查找
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} print(dict1['name']) # Tom print(dict1['id']) # 报错
如果当前查找的key存在,则返回对应的值;否则报错。
- 字典序列.get(key, 默认值)
- 注意:如果当前查找的key不存在则返回第⼆个参数(默认值),如果省略第⼆个参数,则返回 None。
- keys()
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} print(dict1.keys()) # dict_keys(['name', 'age', 'gender'])
- values()
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} print(dict1.values()) # dict_values(['Tom', 20, '男'])
- items()
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} print(dict1.items()) # dict_items([('name', 'Tom'), ('age', 20), ('gender', '男')])
遍历
- 遍历字典的key
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} for key in dict1.keys(): print(key)
- 遍历字典的value
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} for value in dict1.values(): print(value)
- 遍历字典的元素
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} for item in dict1.items(): print(item)
- 遍历键值对
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} for key, value in dict1.items(): print(f'{key} = {value}')
公共操作
运算符
+
in或not in
公共方法
- len()
# 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. 字符串 str1 = 'abcdefg' del str1 # print(str1) NameError: name 'str1' is not defined # 2. 列列表 list1 = [10, 20, 30, 40] del (list1[0]) print(list1) # [20, 30, 40]
- max()
# 1. 字符串 str1 = 'abcdefg' print(max(str1)) # g # 2. 列表 list1 = [10, 20, 30, 40] print(max(list1)) # 40
- min()
# 1. 字符串 str1 = 'abcdefg' print(min(str1)) # a # 2. 列表 list1 = [10, 20, 30, 40] print(min(list1)) # 10
- range()
# 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)
range()⽣成的序列不包含end数字。
- enumerate()
- 语法:enumerate(可遍历对象, start=0),注意:start参数⽤来设置遍历数据的下标的起始值,默认为0。
容器类型转换
- tuple() 转换成元组
list1 = [10, 20, 30, 40, 50, 20] s1 = {100, 200, 300, 400, 500} print(tuple(list1)) # (10, 20, 30, 40, 50, 20) print(tuple(s1)) # (100, 200, 300, 400, 500)
- list() 转换成列表
t1 = ('a', 'b', 'c', 'd', 'e') s1 = {100, 200, 300, 400, 500} print(list(t1)) # ['a', 'b', 'c', 'd', 'e'] print(list(s1)) # [100, 200, 300, 400, 500]
- set() 转换成集合
list1 = [10, 20, 30, 40, 50, 20] t1 = ('a', 'b', 'c', 'd', 'e') print(set(list1)) # {40, 10, 50, 20, 30} print(set(t1)) # {'c', 'a', 'b', 'e', 'd'}
集合可以快速完成列表去重
推导式
列表推导式
需求:创建⼀个0-10的列表。
- while循环实现
# 1. 准备⼀个空列表 list1 = [] # 2. 书写循环,依次追加数字到空列表list1中 i = 0 while i < 10: list1.append(i) i += 1 print(list1)
- for循环实现
list1 = [] for i in range(10): list1.append(i) print(list1)
列表推导式实现
带if的列表推导式
需求:创建0-10的偶数列表
- 方法一:range()步长实现
- 方法⼆:if实现
list1 = [i for i in range(10) if i % 2 == 0] print(list1)
多个for循环创建列表推导式
创建如下列表
字典推导式
字典推导式作用:快速合并列表为字典或提取字典中⽬标数据。
- 创建⼀个字典:字典key是1-5数字,value是这个数字的2次⽅
2. 将两个列表合并为⼀个字典
- 提取字典中⽬标数据
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}
集合推导式
创建⼀个集合,数据为下方列表的2次方。
注意:集合有数据去重功能。
函数
函数就是将⼀段具有独⽴功能的代码块 整合到⼀个整体并命名,在需要的位置调⽤这个名称即可完成对应的需求。 函数在开发过程中,可以更高效的实现代码重⽤。
函数基本使用
- 定义
- 调用
不需要获取返回值
需要获取返回值
- 说明⽂档
定义函数的说明⽂档
查看函数的说明⽂档: help(函数名)
- 嵌套调⽤
所谓函数嵌套调⽤指的是⼀个函数里⾯又调⽤了另外⼀个函数。
如果函数A中,调⽤了另外⼀个函数B,那么先把函数B中的任务都执行完毕之后才会回到上次函数A执⾏的位置。
- 变量作⽤域
变量作用域指的是变量生效的范围,主要分为两类:局部变量和全局变量。
局部变量: 所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。
局部变量的作⽤:在函数体内部,临时保存数据,即当函数调⽤完成后,则销毁局部变量。
全局变量: 所谓全局变量,指的是在函数体内、外都能生效的变量。
在函数体内可通过global关键字声明全局变量
- 返回多个值的处理
只执⾏了第⼀个return,原因是因为return可以退出当前函数,导致return下方的代码不执⾏
- return a, b写法,返回多个数据的时候,默认是元组类型。
- return后⾯可以连接列表、元组或字典,以返回多个值。
- 函数的参数
位置参数: 调⽤函数时根据函数定义的参数位置来传递参数
注意:传递和定义参数的顺序及个数必须⼀致。
关键字参数
函数调⽤,通过“键=值”形式加以指定。可以让函数更加清晰、容易使⽤,同时也清除了参数的顺序需求。
注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。
缺省参数
缺省参数也叫默认参数,⽤于定义函数,为参数提供默认值,调⽤函数时可不传该默认参数的值(注 意:所有位置参数必须出现在默认参数前,包括函数定义和调用)。
函数调⽤时,如果为缺省参数传值则修改默认参数值;否则使用这个默认值。
不定⻓参数
不定⻓参数也叫可变参数。⽤于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进⾏参数传递,会显得非常⽅便。
- 包裹位置传递
def user_info(*args): print(args) # <class 'tuple'> print(type(args)) # ('TOM',) user_info('TOM') # ('TOM', 18) user_info('TOM', 18)
传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple), args是元组类型,这就是包裹位置传递。
- 包裹关键字传递
def user_info(**kwargs): print(kwargs) # {'name': 'TOM', 'age': 18, 'id': 110} user_info(name='TOM', age=18, id=110)
- 拆包和交换变量值
- 拆包
- 拆包:元组
- 交换变量值
- 借助第三变量存储数据。
拆包:字典
方法二
- 引⽤
在python中,值是靠引⽤来传递来的。我们可以⽤ id()来判断两个变量是否为同⼀个值的引用。 我们可以将id值理解为那块内存的地址标
识。
所谓可变类型与不可变类型是指:
数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变.
可变类型 :
- 列表
- 字典
- 集合
不可变类型:
- 整型
- 浮点型
- 字符串
- 元组
函数进阶
- 递归
# 3 + 2 + 1 def sum_numbers(num): # 1.如果是1,直接返回1 -- 出⼝口 if num == 1: return 1 # 2.如果不是1,重复执行累加: result = num + sum_numbers(num - 1) # 3.返回累加结果 return result sum_result = sum_numbers(3) # 输出结果为6 print(sum_result)
image-20201211135449400
- lambda 表达式
- 如果⼀个函数有⼀个返回值,并且只有⼀句代码,可以使用 lambda简化。
语法:
lambda 参数列表 : 表达式
lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适⽤。 lambda函数能接收任何数量的参数但只能返回一个表达式的值
案例1
案例2 计算a + b
lambda的参数形式
无参数
⼀个参数
可变参数:*args
可变参数:**kwargs
带判断的lambda
列表数据按字典key的值排序
- ⾼阶函数
把函数作为参数传入,这样的函数称为⾼阶函数,⾼阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式
案例 1 求两数绝对值和
函数式编程大量使⽤函数,减少了代码的重复,因此程序⽐比较短,开发速度较快。
内置⾼阶函数
- map()
- map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/ 迭代器(Python3)返回。
- reduce()
- reduce(func(x,y),lst),其中func必须有两个参数。每次func计算的结果继续和序列的下⼀个元素做累积计算。
计算 list1 序列中各个数字的累加和
- filter()
- filter(func, lst)函数⽤于过滤序列, 过滤掉不符合条件的元素, 返回⼀个 filter 对象,。如果要转换为列表, 可以使⽤ list() 来转换。
文件操作
⽂件操作的作用就是把⼀些内容(数据)存储存放起来,可以让程序下一次执行的时候直接使用,⽽而不必重新制作一份
文件基本操作
- 打开文件
- 读写等操作
- 关闭⽂件
在python,使⽤open函数,可以打开⼀个已经存在的⽂文件,或者创建一个新⽂件,语法如下:
open(name, mode)
name:是要打开的⽬标文件名的字符串(可以包含文件所在的具体路径)。不包含路径,默认项目根目录
mode:设置打开⽂件的模式(访问模式):只读、写⼊、追加等
image-20201211145024836
创建文件对象:
f = open(name, mode)
写: 对象.write(内容)
读:
- ⽂件对象.read(num): num表示要从⽂件中读取的数据的⻓度(单位是字节),如果没有传入num,那么就表示读取⽂件中所有的数据。
- readlines()
- readlines可以按照行的⽅式把整个⽂件中的内容进⾏⼀次性读取,并且返回的是⼀个列表,其中每⼀行的数据为一个元素。
- readline()
- readline()⼀次读取⼀行内容。
移动文件指针:
⽂件对象.seek(偏移量, 起始位置)
案例1
起始位置:
0:⽂件开头 1:当前位置 2:⽂件结尾,python3种 起始位置不为0的时候,偏移量必须为0
关闭: ⽂件对象.close()
案例 : 备份文件
⽂件和⽂件夹的操作
在Python中文件和⽂件夹的操作要借助os模块里⾯的相关功能
- 导⼊os模块
import os
- 使⽤os 模块相关功能 os.函数名()
- ⽂件重命名
os.rename(⽬标⽂件名, 新⽂件名)
- 删除文件 os.remove(⽬标⽂件名)
- 创建⽂件夹 os.mkdir(⽂件夹名字)
- 删除⽂件夹 os.rmdir(文件夹名字)
- 获取当前目录 os.getcwd()
- 改变默认⽬录 os.chdir(⽬录)
- 获取⽬录列表 os.listdir(⽬录)
面向对象
类和对象
类是对一系列具有相同特征和行为的事物的统称,是⼀个抽象的概念,不是真实存在的事物
- 特征即是属性
- 行为即是方法
对象是类创建出来的真实存在的事物
面向对象实现方法
定义类
类名要满⾜标识符命名规则,同时遵循大驼峰命名习惯。
经典类 不由任意内置类型派生出的类,称之为经典类
创建对象
对象名 = 类名()
创建对象的过程也叫实例化对象。
self
self指的是调⽤该函数的对象。打印对象和self得到的结果是一致的,都是当前对象的内存中存储地址。
添加和获取对象属性
添加语法 :
对象名.属性名 = 值
类外获取语法:
对象名.属性名
, 类内获取语法 self.属性名
魔法方法
在Python中, xx() 的函数叫做魔法⽅法,指的是具有特殊功能的函数
__init__
方法的作⽤:初始化对象,赋予属性默认值__init__
方法,在创建⼀个对象时默认被调用,不需要⼿动调⽤ __init__(self)
中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。__str__
方法,类似Java的toString,当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了 __str__
方法,那么就会打印从在这个方法中 return 的数据__del__
当删除对象时,python解释器也会默认调⽤ del() 方法。__mro__
方法:获取这个类的调用顺序继承
Python⾯向对象的继承指的是多个类之间的所属关系,即⼦类默认继承⽗类的所有属性和⽅法在Python中,所有类默认继承object类,object类是顶级类或基类;其他⼦类叫做派⽣类。
多继承
所谓多继承意思就是一个类同时继承了多个父类。当⼀个类有多个父类的时候,默认使⽤第一个⽗类的同名属性和方法。
⼦类重写⽗类同名⽅法和属性
⼦类和⽗类具有同名属性和⽅法,默认使⽤⼦类的同名属性和⽅法
多层继承
super 关键字
使⽤super() 可以自查找⽗类。调⽤顺序遵循
__mro__
类属性的顺序。⽐较适合单继承使用。私有权限
- 定义私有属性和方法
- 在Python中,可以为实例属性和⽅法设置私有权限,即设置某个实例属性或实例⽅法不继承给⼦类。
- ⼦类⽆法继承⽗类的私有属性和私有方法
- 对象不能直接访问私有属性和私有方法
- 私有属性和私有⽅法只能在类⾥面访问和修改。
设置私有权限的方法:在属性名和⽅法名前面 加上两个下划线
注意:
- 获取和修改私有属性值
在Python中,⼀般定义函数名 get_xx ⽤来获取私有属性,定义 set_xx ⽤来修改私有属性值
⾯向对象三大特性
- 封装
- 将属性和⽅法书写到类的里⾯的操作即为封装
封装可以为属性和⽅法添加私有权限
- 继承
- ⼦类默认继承父类的所有属性和⽅法
⼦类可以重写父类属性和方法
- 多态
- 传⼊不同的对象,产⽣不同的结果
类属性和实例属性
类属性就是类对象所拥有的属性,它被该类的所有实例对象所共有
类属性可以使⽤类对象 或 实例对象访问
类的实例记录的某项数据始终保持⼀致时,则定义类属性。
实例属性 要求每个对象为其单独开辟一份内存空间来记录数据,而类属性为全类所共有 ,
仅占⽤一份内存,更加节省内存空间
修改类属性
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。
实例属性不能通过类访问
类方法和静态方法
- 类方法
- 第⼀个形参是类对象的⽅法
- 需要用装饰器 @classmethod 来标识其为类⽅法,对于类方法,第⼀个参数必须是类对象,⼀般以 cls 作为第⼀个参数
- 使用场景
- 当方法中需要使用类对象 (如访问私有类属性等)时,定义类方法
- 类⽅法⼀般和类属性配合使用
- 静态方法
- 需要⽤装饰器 @staticmethod 来标识其为静态方法,静态⽅法既不需要传递类对象也不需要传递实例对象 (形参没有self/cls)
- 静态⽅方法 也能够通过 实例例对象 和 类对象 去访问
- 使用场景
- 当⽅法中 既不需要使⽤实例对象(如实例对象,实例属性),也不需要使⽤类对象 (如类属性、类⽅法、创建实例等)时,定义静态方法
- 取消不需要的参数传递,有利于减少不必要的内存占⽤和性能消耗
异常
语法
案例
捕获指定异常
- 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则⽆法捕获异常。
- 一般try下方只放⼀行尝试执行的代码。
捕获多个指定异常
当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的⽅式进行书写
捕获异常描述信息
捕获所有异常
Exception是所有程序异常类的⽗类。
异常的else
else表示的是如果没有异常要执行的代码。
异常的finally
finally表示的是⽆论是否异常都要执行的代码,例如关闭文件。
异常传递
- 当函数/方法执行出现异常,会将异常传递给函数/方法的调用方
- 如果传递到主程序,仍然没有异常处理,程序才会被终止
自定义异常
在Python中,抛出自定义异常的语法为 raise 异常类对象
模块和包
- 模块
- Python 模块(Module),是⼀个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。 模块能定义函数,类和变量,模块⾥也能包含可执行的代码
- 导⼊模块
- 方式:
- import 模块名
- 语法
- from 模块名 import 功能名
- 语法
- from 模块名 import *
- 语法
- import 模块名 as 别名
- from 模块名 import 功能名 as 别名
- as定义别名
例
例
例
例
# 模块2代码
def my_test(a, b):
print(a - b)
# 导⼊入模块和调⽤用功能代码
from my_module1 import my_test
from my_module2 import my_test
# my_test函数是模块2中的函数
my_test(1, 1)
```模块定位顺序
当导⼊一个模块,Python解析器对模块位置的搜索顺序是:
def testA():
print('testA')
def testB():
print('testB')
python
from myModule1 import *
testA()
testB()
# testA
# Traceback (most recent call last):
# File "E:/study/PyProjects/pachong/myPyTest1.py", line 5, in
# testB()
# NameError: name 'testB' is not defined
```- 包
- 包将有联系的模块组织在一起,即放到同⼀个文件夹下,并且在这个文件夹创建⼀个名字为 init.py ⽂件,那么这个⽂件夹就称之为包
制作包
image-20201216092928719
新建包后,包内部会⾃动创建 init.py 文件,这个文件控制着包的导入⾏为
例
- 新建包 mypackage
- 新建包内模块: my_module1 和 my_module2
- 模块内代码如下
导入包
方法一
import 包名.模块名 包名.模块名.目标
⽅法⼆
必须在 init.py ⽂件中添加 all = [] ,控制允许导入的模块列表。
python 应用
网络爬虫
request库安装
pip3 install requests
Beautiful Soup4 安装 :
pip3 install bs4
pip3 install lxml