Python语法基础篇(包含类型转换、拷贝、可变对象/不可变对象,函数,拆包,异常,模块,闭包,装饰器)
Python语法基础篇(二)
- 类型转换
- 拷贝
- 可变对象与不可变对象
- 可变对象
- 不可变对象
- 函数
- 拆包
- 异常
- 模块
- 闭包
- 装饰器
🐹🐹🐹🐹🐹一只正在努力学习计算机技术的小仓鼠,尾部有课程链接哦~🐹🐹🐹🐹🐹
类型转换
int()
:转换成整型print(int(1.8))
float()
:转换成浮点型print(float(5))
str()
:转换成字符串print(str(5.00))
eval()
:实现list、dict、tuple和string之间的转换 — 去引号,但是不安全(详见RCE)s = "[[1,2,3],[4,5,6]]" slist = eval(s) print(slist,type(slist))
list()
:将可迭代对象转换成列表 注:可迭代对象指能用for循环遍历的对象;支持转换为list的类型: string、tuple、dict、set# str -> list print(list('abc')) # tuple -> list print(list((1,2,3,4))) # dict -> list print(list({'name':'zhangsan', 'age':18})) # set -> list print(list({'a','b','c','d','e','f','g','h'}))
拷贝
- 深拷贝:创建一个新对象,新对象涵盖所有层级的对象属性和数组元素,新对象与原对象不共用内存。
import copy a = [1,2,3,[4,5,6]] acopy = copy.deepcopy(a) print(id(a),id(acopy)) a[3].append(7) print(a,acopy)
- 浅拷贝:创建一个新对象,只复制指针,该指针指向与原数据共同的对象。
import copy a = [1,2,3,[4,5,6]] acopy = copy.copy(a) print(id(a),id(acopy)) a[3].append(7) print(a,acopy)
- 浅拷贝与深拷贝的区别详解
可变对象与不可变对象
可变对象
- 概念:存储空间保存的数据允许被增加、删除或修改,但内存地址不会发生改变,这种数据就是可变类型。
Python中可变对象有list、set、dict
li = [1,2,3,4] print(li,id(li)) li.append(5) print(li,id(li))
不可变对象
- 概念:变量对应的值不能被修改,如果修改就会生成一个新的值从而分配新的内存空间。
Python中不可变对象有tuple、int、float、string
st = 'hello' print(id(st)) st = 'bingbing' print(id(st))
函数
- 概念:将独立的代码块组织成一个整体,使其具有特定功能。
- 普通函数
- 格式
def 函数名():函数体return 返回值1, 返回值2 ...# 调用 函数名()
- 返回值类型
- 没有返回值:None
- 一个返回值:该值
- 多个返回值:元组
- 参数类型
- 必备参数,默认参数 注:必备参数必须在默认参数前面。
# x,y为必备参数;z为默认参数 def my_add(x,y,z=10):return x+y+zp = my_add(1,2) q = my_add(1,2,3) print(p,q)
- 可变参数:传入参数类型为元组,数量可以改变。
def afunc(*args):tuple_to_list = list(args)print(args)print(tuple_to_list) afunc(1, 2, [3, 4])
- 关键字参数:参数以字典的形式传值。
def bfunc(**kwargs):for i in kwargs.keys():print(i, type(i))print(kwargs[i], type(kwargs[i])) bfunc(name='zhangsan',age=18)
- 必备参数,默认参数 注:必备参数必须在默认参数前面。
- 函数嵌套:在一个函数里定义另一个函数
def cfunc():print('this is cfunc')def dfunc():print('this is dfunc')# 定义和调用同级(同缩进)dfunc() cfunc()
- 作用域:按照变量生效范围可分为全局变量和局部变量
- 全局变量
a = 100 def test1():print('a的值为%d' % a) test1()
# 全局变量__name__ # 作用:用于控制py文件在不同的应用场景执行不同的逻辑# 文件在当前程序执行:__name__ == '__main__'# 文件被当作模块导入时,不执行__name__ == '__main__' import pytest_1 pytest_1.test()# pytest_1.py print('这是pytest2作为模块会显示的内容') def test():print('哈哈哈') if __name__ == '__main__':print('这是pytest2作为模块不会显示的内容')
- 局部变量
a = 120 def test2():a = 100 print('a的值为%d' % a) test2() print('a的值为%d' % a)
global 变量名
:将变量声明为全局变量,用于修改全局变量值a = 120 def test2():global aa = 100print('a的值为%d' % a) test2() print('a的值为%d' % a)
nonlocal 变量名
:用于声明外层的局部变量def test3():a = 100def inner_func():nonlocal aa = 120print('a的值为%d' % a)inner_func()print('a的值为%d' % a) test3()
- 全局变量
- 格式
- 匿名函数
- 无参数
funa = lambda : '一桶水果茶' fruit_tea = funa() print(fruit_tea)
- 必要参数
函数名 = lambda 形参:返回值(表达式)
add = lambda a,b:a+b #a,b就是匿名函数的形参,a+b是返回值的表达式 total = add(1,2) print(total)
- 默认参数:默认参数必须写在必要参数后面
funb = lambda name,age=18:(name,age) info_a = funb('张三') info_b = funb('李四', 20) print(info_a,'\n',info_b)
- 可变参数
func = lambda **kwargs:kwargs print([func(name='张三',age=18)])
- lambda与if函数结合(三目运算符)
fund = lambda a,b:a if a<b else b print(fund(1,2))
- 无参数
- 内置函数
- 查看所有内置函数:大写字母开头一般是内置常量名,小写字母开头一般是内置函数名
import builtins print(dir(builtins))
abs()
:返回绝对值sum()
:求和 — 元组,集合,数组print(sum([2,3]))
min()
:求最小值max()
:求最大值print(min(-2,3, key=abs))
zip()
:将可迭代对象作为参数,将对象中的元素一一对应打包成元组(如果元素不一致,就按照长度最短的返回)l1 = [1,2,3] l2 = ['a','b'] print(zip(l1,l2)) for i in zip(l1,l2):print(i, type(i)) # 转换成列表打印(条件:必须是可迭代对象) print(list(zip(l1,l2)))
map(function, iterable)
:对可迭代对象中的每一个元素进行映射。list1 = [1,2,3] def func(a,b=1):return a+b # 对象形式的数据有两种提取方式: (1)数组 (2)for循环 print(list(map(func,list1))) print(list(map(lembda a,b=1:a+b, list1)))
reduce(function, sequence)
:将对象中的两个元素取出作为函数的实参进行运算,运算的结果和第三个元素作为函数的实参再进行运算。function:必须是有且仅有两个必要参数的函数sequence:必须是可迭代对象
from functools import reduce list2 = [1,2,3] def add(x, y, z=1):return x+y+z print(reduce(add, list2))
- 查看所有内置函数:大写字母开头一般是内置常量名,小写字母开头一般是内置函数名
- 递归函数
- 概念:如果一个函数在内部不调用其他函数, 而是调用它本身, 这个函数就是递归函数。
def acc(number): if number == 0:return 0 else:return number + acc(number-1) print(acc(10)) # 斐波那契数列 def fabnacci(number):if number == 1 or number == 2:return 1else:return fabnacci(number-1) + fabnacci(number-2) for i in range(31):if i > 0:print(fabnacci(i), end=',')
- 概念:如果一个函数在内部不调用其他函数, 而是调用它本身, 这个函数就是递归函数。
拆包
- 概念:对于函数中的多个返回数据,去掉元组、列表或字典,直接获取数据的过程
tua = (1,2,3) print(tua,type(tua)) # 拆解方法一 a,b,c = tua print(a,b,c) # 拆解方法二 a, *b = tua print(a, *b) # 一般在函数调用时使用 def funa(a,b,*args):print(a,b)print(args,type(args)) arg = [1,2,3,4,5,6] funa(*arg)
异常
- 概念:当Python检测到一个错误时,解释器就无法继续执行下面的语句,反而会出现一些错误的提示。
- 异常类型
异常类型 释义 AttributeError 尝试访问或设置一个对象不存在的属性或方法 IOError 输入/输出异常,例如无法打开文件 ImportError 无法引入模块和包,例如路径错误或名称错误 IndentationError 语法错误(的子类),例如代码没有正确对齐 IndexError 下标索引超出序列边界 KeyError 视图访问字典里不存在的键 SyntaxError 代码非法, 代码不能编译 TypeError 传入对象类型与要求的不符合 ValueError 传入一个调用者不期望的值 - 异常处理:程序有异常时,整个程序仍能正常运行
- 语法:
try:可能引发异常现象的代码 except:出现异常现象的处理代码 else:只有在没有异常时才会执行的代码 finally:try代码块结束后执行的代码
- 示例:
# 方法1: try:print(abc) except NameError as e:print(e) # 方法2 -- 捕获任何异常 try:print(abc) except Exception as e:print(e) # 方法3 -- 多分支异常 try:print(abc) except IndexError as e:print(e) except KeyError as e:print(e) except NameError as e:print(e) # else dic = {'name':'zhangsan'} try:print(dic['age']) except Exception as e:print('出现错误') else:print(dic) # finally try:print(dic['age']) except Exception as e:print(e) finally:print(dic)
- 语法:
- 抛出异常
raise
- 创建一个Exception(‘xxx’)对象
- raise抛出这个异常对象
# 需求:密码长度不足六位就重新输入,输入超过三次错误就报异常 def login():for i in range(3):pwd = input('请输入密码:')if len(pwd) >= 6:return '密码输入成功'elif i != 2:print('密码长度不足六位,请重新输入')raise Exception('输入错误超过三次,退出') try:login() except Exception as e:print(e)
模块
- 概念:一个py文件就是一个模块,即导入一个模块本质上就是执行一个py文件。
- 分类
- 内置模块:random、time、os、logging
- 第三方模块:pip install 包名
- 自定义模块:自己在项目中定义的模块
# 导入模块 import numpy # 调用功能 l1 = [1,2,3] l1 = numpy.append(l1,[4,5,6]) print(l1) # 从模块中导入指定的部分 from numpy import split # as起别名 import pandas as pd
- 包
- 概念:项目结构中的文件夹/目录。包的本质是模块,包可以包含包。
- 作用:将有联系的模块放到同一个文件夹下,并且在该文件夹中创建一个__init__.py的文件。包能够有效避免模块名称的冲突问题,使结构更清晰。
# import导入包时, 首先执行__init__.py文件 # __all__ 本质是一个列表, 列表里面的元素代表要导入的模块。# Pack_01是Python Package from Pack_01 import * Register.reg()# __init__.py # 不建议在__init__.py中写过多代码, 尽量保证init的内容简单 # 主要作用: 导入这个包内的其它模块 # from Pack_01 import Register __all__ = ['Register']# Register.py def reg():print('这是reg函数')
闭包
- 内部函数构成闭包的条件:
- 嵌套函数
- 内部函数使用外部函数的变量
- 外部函数返回内部函数
- 无参数
def funcA():a = 10def funcB():print(a)return funcB # 第一种调用方法 print(funcA()) funcA()() # 第二种调用方法 ot = funcA() ot()
- 默认参数
# 函数名保存函数地址,()理解成指针 def outer(m):n = 10def inner(p):print(m+n+p)return inner ot = outer(5) ot(5)
- 思维训练
def result(**kwargs):identity = {'code':0}identity['code'] = kwargs['add']def tup(*args):for i in args:identity['code'] += idef outer(a,b=1):identity['code'] += a+breturn kwargs.get('add')return outerreturn tup result(add=10)(1,2,3,4)(9) # 每次开启内函数都在使用同一份闭包变量 print(result(add=10)(1,2,3,4)(9))
装饰器
- 概念:装饰器本质上是一个闭包函数,它可以让其他函数不需要做任何变动的情况下增加额外功能,装饰器的返回值是一个函数对象。
- 作用:在不改变原有代码情况下添加新的功能
- 条件:
- 不修改源程序或函数的代码
- 不改变函数或程序的调用方法
- 单个装饰器
# 形参是函数 def test(fn):print('test')fn() def HaHa():print('HaHa') test(HaHa)# 标准版装饰器 def send():print('send message') def outer(fn):def inner():# 原有功能 --- send()fn()# 新功能print('check message info')return inner outer(send)()
- 多个装饰器
def deco_1(fn):def inner():return "哈哈哈"+fn()+"呵呵呵"return inner def deco_2(fn):def inner():return "nice"+fn()+"excellent"return inner # 多个装饰器的装饰过程,距离函数最近的装饰器先装饰。 # deco_2 -> "nice"+test()+"excellent" # deco_1 -> "哈哈哈"+demo_2()+"呵呵呵" @deco_1 @deco_2 def test():return "晚上在学习python" print(test())
- 语法糖
- 格式:
@装饰器名称
- 无参数
def outer(fn):def inner():fn()print('send message')return inner @outer def YYDS():print('YYDS') YYDS()
- 有参数
# 有参数 user = [{'username':'zhangsan', 'password':'123456'}] def outer(fn):def inner(user):for i in range(len(user)):for j in user[i].keys():if j == 'username':print(f'用户:{user[i][j]}',end=',')else:print(f'密码:{user[i][j]}')fn(user)return inner @outer def login(user):while True:username = input('请输入用户名:')pwd = input('请输入至少六位密码:')if len(pwd) < 6:print('请重新输入')continueelse:user.append({'username':username, 'password':pwd})breakfor i in range(len(user)):for j in user[i].keys():if j == 'username':print(f'用户:{user[i][j]}', end=',')else:print(f'密码:{user[i][j]}') login(user)
- 格式:
课程链接