python基础语法(3) -------- 学习笔记分享
目录:
1. 函数
1.1 语法格式
1.2 函数参数
1.3 函数返回值
1.4 变量的作用域
1.5 函数的执行过程
1.6 函数的链式调用
1.7 函数的嵌套调用
1.8 函数递归
1.9 参数默认值
1.10 函数的关键字传参
2. 列表和元组
2.1 列表和元组是啥
2.2 创建列表
2.3 访问下标
2.4 切片操作
2.5 遍历列表元素
2.6 新增元素
2.7 查找元素
2.8 删除元素
2.9 连接列表
2.10 关于元组
3. 字典
3.1 字典是什么
3.2 创建字典
3.3 查找key
3.4 新增 / 修改元素
3.5 删除元素
3.6 遍历字典元素
3.7 取出所有key和value
3.8 合法的key类型
4. 文件
4.1 文件是什么
4.2 文件路径
4.3 文件操作
4.4 关于中文的处理
4.5 使用上下文管理器
题外话:PEP8 是python里面的一套非常流行的编程规范;也就是写代码的一些"软性要求"
1. 函数
一段可以被重复使用的代码
1.1 语法格式
创建函数/定义函数
def 函数名(形参列表): 函数体 return 返回值
调用函数/使用函数
函数名(实参列表) //不考虑返回值 返回值 = 函数名(实参列表) //考虑返回值
-
函数定义并不会执行函数体内容,必须要调用才会执行
1.2 函数参数
跟C里面理解上差不多,不赘述
1.3 函数返回值
大部分跟C/C++一样
但是python中的一个函数可以返回多个值!!!特别香的特性
def getPoint(): x = 10 y = 20 return x, y a,b = getPoint()
虽然现在能返回多个值,但只想使用其中的一部分返回值,该怎么办呢?
python可以使用下划线 _ 进行占位
_,b = getPoint()
这个就是不要x,只要y,把y赋值给b
1.4 变量的作用域
变量只能在所在的函数内部生效
在函数getPoint()内部定义的x,y只是在函数内部生效,一旦处理函数的范围,这两个变量就不再生效了
在不同的作用域中,允许存在同名的变量
虽然名字相同,实际上是不同的变量
在函数立场是读取全局变量是可以的!
当函数中尝试访问某个变量的时候,会现场时在局部变量中查找,如果找到,就直接访问;
如果没找到,就会往上一级作用域中进行查找~
要想在函数内部修改局部变量,需要使用python中的关键字: global
x = 10 def test(): global x x = 20 test() print(f'x = {x}')
关键字 global关键字可以声明x是全局变量
另外,
if,else,while,for 这些关键字也会引入"代码块",但是这些代码块不会对变量的作用域产生影响!!!
在上述语句的代码块内部定义的变量,可以在外面被使用
1.5 函数的执行过程
-
调用函数才会执行函数体代码
-
函数体执行结束(或者遇到return语句),则回到函数调用位置,继续往下执行
题外话:
点击行号右侧的空白,可以在代码中插入断点
右键,debug,可以按照调试模式执行代码,每次执行到断点,程序都会暂停下来
使用Step Into (F7)功能可以逐行执行代码
1.6 函数的链式调用
把一个函数的返回值,作为另一个函数的参数,这种操作就叫做链式调用
print(isOdd(10))
1.7 函数的嵌套调用
函数的内部还可以调用其他的函数
def test(): print('1') print('2') print('3')
一个函数里面可以嵌套任意多个函数
1.8 函数递归
递归是嵌套调用中的一种特殊情况,即一个函数嵌套调用自己
代码示例:递归计算5!
def factor(n): if n == 1: return 1 return n * factor(n - 1) result = factor(5) print(result)
递归代码需要两个要素: 1. 递归结束条件 2. 递归的递归公式
递归缺点:1. 执行过程非常复杂 2. 递归代码容易出现"栈溢出"情况
1.9 参数默认值
python中的函数,可以给形参指定默认值
带有默认值的参数,可以在调用的时候不传参
代码示例:计算两个数字的和
def add(x,y,debug=False) if debug: print(f'调试信息:x={x},y={y}') return x+y print(add(10,20)) print(add(1,22,True))
带有默认值的参数需要放到没有默认值的参数的后面
1.10 函数的关键字传参
一般编程语言函数传参都是按照先后顺序来传参~这种风格叫做"位置传参"
但python另有一种传参方式叫做 : 关键字传参
def test(x,y): print(f'x = {x}') print(f'y = {y}') test(y=10,x=20)
2. 列表和元组
2.1 列表和元组是啥
列表是一种让程序员在代码中批量显示/保存数据的方式
元组和列表相比,是非常相似的,只是列表中放哪些元素可以修改调整,元组中放的元素是创建元组的时候就设定好的,不能修改调整
2.2 创建列表
-
创建列表主要有两种方式, [ ]表示一个空的列表
alist = [ ]//方法1 alist = list()//方法2 print(type(alist))
-
如果需要往里面设置初始值,可以直接写在[ ]
可以直接使用print来打印list中的元素内容
alist = [1,2,3,4] print(alist)
-
列表中存放的元素允许是不同的类型.(这一点和C++ java差别很大)
alist = [1,'hello',Ture] print(alist)
因为list本身是Python中的内建函数,不宜在使用list作为变量名,因此命名为alist
2.3 访问下标
-
可以通过下标访问操作符[ ]来获取到列表中的任意元素
我们把[ ]中填写的数字,称为
下标
或者索引
alist = [1,2,3,4] print(alist[2])
注意:下标是从0开始的
-
通过下标不光能读取元素内容,还能修改元素的值
alist = [1,2,3,4] alist[2] = 100 print(alist)
-
如果下标超出列表的有效范围,会抛出异常
alist = [1,2,3,4] print(alist[100])
-
因为下标是从0开始的,因此下标的有效范围是[0,列表长度-1],使用
len
函数可以获取到列表的元素个数
alist = [1,2,34,4] print(len(alist))
-
下标可以取负数,表示"倒数第几个元素"
alist = [1,2,34,4] print(alist[-1])
2.4 切片操作
通过下标操作是一次取出里面的第一个元素
通过切片,则是一次取出一组连续的元素,相当于得到一个子列表
-
使用[ : ]的方式进行切片操作
alist = [1,2,3,4] print(alist[1:3])
表示的是[1,3)这样的有下标构成的前闭后开的区间
也就是下标为1和2的元素
-
切片操作中可以省略前后边界
alist = [1,2,3,4] print(alist[1:]) print(alist[:-1]) print(alist[:])
-
切片操作还可以指定"步长",也就是"每访问一个元素后,下标自增几步"
alist = [1,2,3,4,5,6,7,8,9,10] print(alist[::1]) print(alist[::2]) print(alist[::3])
步长的数值也可以是负的,意思是从后往前来取元素
2.5 遍历列表元素
"遍历"指的是把元素一个一个的取出来,再分别进行处理
-
最简单的办法就是使用for循环
alist = [1,2,3,4] for elem in alist: print(elem)
-
也可以使用for按照范围生成下标,按下标访问
alist = [1,2,3,4] for i in range(0,len(alist)): print(alist[i])
-
还可以使用while循环,手动控制下标的变化
alist = [1,2,3,4] while i < len(alist): print(alist[i]) i += 1
2.6 新增元素
-
使用
append
方法,向列表末尾插入一个元素(尾插)
alist = [1,2,3,4] alist.append('hello') print(alist)
-
使用
insert
方法,向任意位置插入一个元素
insert 第一个参数表示要插入元素的下标
alist = [1,2,3,4,5] alist.insert(1,'hello') print(alist)#打印[1,'hello',2,3,4,5]
注意:如果上述代码中是alist.insert(100,'hello')
,那么只会在5的后面插入'hello',而不会扩充列表至100
上述方法就是函数,只不过函数是独立存在的,而方法往往要依附于某个"对象"
像上述代码中的
alist.appned
,append就是依附于alist,相当于是"针对alist这个列表进行尾插操作"
2.7 查找元素
-
使用
in
操作符,判定元素是否存在于列表中,返回值是布尔类型
alist = [1,2,3,4] print(2 in alist)#True print(10 in alist)#False print(10 not in alist)
-
使用
index
方法,查找元素在列表中的下标,返回值是一个整数,如果元素不存在,则会抛出异常
alist = [4,3,2,1] print(alist.index(2)) print(alist.index(10))
2.8 删除元素
-
使用
pop
方法删除列表最后一个元素
alist = [1,2,3,4] alist.pop() print(alist)
-
pop
也能按照下标来删除元素
alist = [1,2,3,4] alist.pop(2) print(alist)
-
使用
remove
方法,按照值删除指定元素
alist = ['aa','bb','cc','dd'] alist.remove('aa') print(alist)
2.9 连接列表
-
使用
+
能够把两个列表拼接在一起
此处的
+
结果会生成一个新的列表,而不会影响到旧列表的内同
alist = [1,2,3,4] blist = [5,6,7] print(alist + blist)
-
使用
extend
方法,相当于把一个列表拼接到另一个列表的后面
a.extend(b),是吧b中的内容拼接到a的末尾,不会改变b,但是会修改a
alist = [1,2,3,4] blist = [5,6,7] alist.extend(blist) print(alist) print(blist)
2.10 关于元组
元组的功能和列表相比,基本是一致的
a = (1,2,3,4)#创建元组
元组使用( )来表示
atuple = ( ) atuple = tuple()
元组不能修改里面的元素,列表可以修改里面的元素
因此,像读操作,比如访问下标 \ 切片 \ 遍历 \ in \ index \ + 等,元组也是一样支持
但是,像写操作,比如修改元素 \ 新增元素 \ 删除元素 \ extend 等,元组则不能支持
另外,元组在python中很多时候是默认的集合类型,例如,当一个函数返回多个值的时候
def getPoint(): return 10,20 result = getPoint() print(type(result))
此处的result
的类型,其实就是元组
既然已经有了列表,为啥还需要有元组?
元组相比列表来说,优势有两方面:
你有一个列表,现在需要调用一个函数进行一些处理,但是你又不是特别确认这个函数是否会把你的列表数据弄乱,那么这时候传一个元组就安全很多
字典(一个键值对结构),要求字典的键必须是"可hash对象"(字典的本质上也是一个hash表),而一个可hash对象的前提就是不可变,因此元组可以作为字典的键,但是列表不行
3. 字典
3.1 字典是什么
字典是一种存储键值对
的结构
把键(key)和值(value)进行一个一对一
的映射,然后就可以根据键,快速找到值
学号和学生的关系
3.2 创建字典
-
创建一个空的字典,使用{ }表示字典
a = { } b = dict() print(type(a)) print(type(b))
-
也可以在创建的同时指定初始值
-
键值对之间使用
,
分割 ; 键和值之间使用:
分割 (冒号后面推荐加一个空格) -
使用print打印字典内容
student = {'id': 1 , 'name' : 'zhangsan'} print(student)
为了代码更规范美观,在创建字典的时候往往会把多个键值对,分成多行来书写
student = { 'id' : 1, 'name' : 'zhangsan' }
3.3 查找key
-
使用
in
可以判定key是否在 字典 中存在,返回布尔值
使用方法同上文,但注意,in
只是判定 key 是否存在,与value无关 !
-
使用[ ]用过类似于取下标的方式,获取元素的值,只不过此处的"下标"是key(可能是整数,也可能是字符串等其他类型)
student = { 'id' : 1, 'name' : 'zhangsan' } print(student['id']) print(student['name'])
-
如果key在字典中不存在,就会抛出异常
3.4 新增 / 修改元素
使用[ ]可以根据key来新增 / 修改 value
-
如果key不存在,对去下标操作赋值,即为新增键值对
student = { 'id' : 1, 'name' : 'zhangsan' } student['score'] = 90 print(student)
-
如果key已经存在,对取下标操作赋值,即为修改键值对的值
student = { 'id' : 1, 'name' : 'zhangsan', 'score' : 80 } student['score'] = 90 print(student)
3.5 删除元素
-
使用
pop
方法来根据 key 删除键值对
student.pop('name')
3.6 遍历字典元素
-
直接使用for循环能够获取到字典中的所有key,进一步的就可以取出每个值了
student = { 'id' : 1, 'name' : 'zhangsan', 'score' : 80 } for key in student: print(key,student[key])
3.7 取出所有key和value
-
使用
keys
方法可以获取字典中的所有的key
student = { 'id' : 1, 'name' : 'zhangsan', 'score' : 80 } print(student.keys())
此处
dict_keys
是一个特殊的类型,专门用来表示字典的所有key. 是一个自定义类型使用的时候也可以把她当作一个列表来使用
大部分元组支持的操作对于
dict_keys
同样适用
-
使用
values
方法可以获取到字典中的所有value
print(student.values())
此处
dict_values
也是一个特殊类型,和dict_keys类似
-
使用
items
方法可以获取到字典中所有的键值对
print(student.items())
首先是一个列表一样的结构,里面每个元素又是一个元组,元组里面包含了键和值~
for key,value in student.items(): print(key,value)
3.8 合法的key类型
不是所有的类型都可以作为字典的key
字典本质上是一个哈希表
. 哈希表的key要求是"可哈希的",也就是可以计算出一个哈希值.
-
可以使用
hash
函数计算某个对象的哈希值 -
但凡能够计算出哈希值的类型,都可以作为字典的key
print(hash(0)) print(hash(3.14)) print(hash('hello')) print(hash(True)) print(hash()) # ( )是一个空的元组
-
列表无法计算哈希值
-
字典也无法计算哈希值
4. 文件
4.1 文件是什么
~省略~
4.2 文件路径
为了方便确定一个文件所在的位置,使用文件路径来进行描述
以盘符开头的路径,我们也成为绝对路径.
除了绝对路径之外,还有一种常见的表示方式是相对路径.相对路径需要先制定一个基准目录,然后以基准目录为参照点,间接的找到目标文件.
4.3 文件操作
要使用文件,主要是通过文件来保存数据,并且在后续把保存的数据读取出来.
但是想要读写文件,需要先"打开文件",读完之后还要"关闭文件"
(1) 打开文件
使用内建函数open
打开一个文件
f = open('d:/test.txt',r)
如果文件打开成功,返回一个文件对象,后续的读写文件操作都是围绕这个文件对象展开
如果文件打开失败,就会抛出异常
(2) 关闭文件
使用close
方法关闭已经打开的文件
f.close()
使用完毕的文件要记得即使关闭 !
一个程序能同时打开的文件个数,是存在上限的
flist = [] count = 0 while True: f = open('d:/test.txt','r') flist.append(f) count += 1 print(f'count = {count}')
注意 : 上述代码中,使用一个列表来保存了所有的文件对象.如果不进行保存,那么Python内置的垃圾回收机制(GC),会在文件对象销毁的时候自动关闭文件.
但是由于垃圾回收操作不一定及时,所以我们写代码仍然要考虑手动关闭,尽量避免依赖自动关闭
(3) 写文件
文件打开之后,就可以写文件了.
-
写文件,要使用写方式打开,
open
第二个参数设为'w'
-
使用
write
方法写入文件
f = open('d:/test.txt','w') f.write('hello') f.close
-
如果是使用
'r'
方式打开文件,则写入时会抛出异常 -
使用
'w'
一旦打开成功,就会清空文件原有的数据 -
使用
'a'
实现"追加写",此时原有内容不变,写入的内容会在于之前文件内容的末尾
(4) 读文件
-
读文件内容需要使用
'r'
的方式打开文件 -
使用
read
方法完成读操作,参数表示"读取几个字符"
f = open('d:/test.txt','r') result = f.read(2) print(result) f.close()
-
分行读取
f = open('d:/test.txt','r') for line in f: print(f'line = {line}',end = ' ') #end参数表示在每次打印末尾加啥,默认是换行 f.close()
-
还可以使用
readlines
方法直接把整个文件所有内容都读出来,按照行组织到一个列表中
f = open('d:/test.txt','r') lines = f.readline() print(lines) f.close()
4.4 关于中文的处理
f = open('d:/test.txt','r',encoding = 'utf8')
4.5 使用上下文管理器
打开文件之后,是容易忘记关闭的,Python提供了上下文管理器,来帮助程序员自动关闭文件
-
使用with语句打开文件
-
当with内部的代码块执行完毕后,就会自动调用关闭方法.
with open('test.txt','r',encoding= 'utf8') as f: