文章目录
- 函数
- 内置函数函数的使用
- 查看函数的帮助信息
- 数学相关
- 类型转换
- 功能相关
- 自定义函数,参数类型检查
- 自定义函数
- 参数类型检查
- 默认、可变、关键,命名参数
- 默认参数
- 可选参数
- 关键字参数
- 命名关键字参数
- 接受任意参数
- 自定义函数
- 空函数
- 函数的返回值,返回一个函数
- 递归函数
- 变量作用域和命名空间
- 变量作用域
- global关键字(局部中让外部生效)
- 命名空间
- 获取命名(locals)
- 获取命名(globals)
- 高级特性(迭代和列表生成式)
- 迭代
- 列表生成式
- 生成器
- 高阶函数
- 自定义高阶函数
- 内置高阶函数
- 匿名函数和装饰器
- 匿名函数
- 装饰器
函数
函数是实现特定功能的代码段的封装,在需要的时候可以多次调用函数来实现该功能。
内置函数函数的使用
python内置了许多非常有用的函数,可以直接调用,下面是部分展示。
查看函数的帮助信息
help(名称)
数学相关
1、绝对值:abs(-1)
2、最大最小值:max([1,2,3])、min([1,2,3])
3、序列长度:len('abc')、len([1,2,3])、len((1,2,3))
4、取模:divmod(5,2)
5、乘方:pow(2,3,4)
6、浮点数:round(1)
类型转换
1、int(x)
2、str(x)
3、float(x)
4、bool()
# 布尔值判断
5、list(x)
6、tuple(x)
#元组
7、hex(x)
8、ord(x)
#返回字符对应的ASC码数字编号,如ord(‘A’)返回65
9、chr(x)
#返回x对应的字符,如chr(65)返回‘A’
功能相关
1、函数是否可调用:callable(funcname)
,注意,funcname变量要定义过(类和类内…),且像整数,字符串,列表,元组,字典等等,都是不可调用的!
2、类型判断:isinstance(x,list/int)
3、快速生成序列:它的语法:range(start, stop [,step])
;start 指的是计数起始值,默认是 0;stop 指的是计数结束值,但不包括 stop ;step 是步长,默认为 1,不可以为 0 。range() 方法生成一段左闭右开的整数范围。
必须是整数,可以是负数,但不能是浮点数等其它类型;(3)它是不可变的序列类型,可以进行判断元素、查找元素、切片等操作,但不能修改元素;(4)它是可迭代对象,却不是迭代器。
print(range(5,10))
for x in range(5,10) : # 默认取值
print(x,end=' ')
print()
for y in range(5,10,2) : # 每隔2个取一次值
print(y,end=' ')
自定义函数,参数类型检查
适用于需要多次重复使用相当功能的情况下 定义函数并调用函数。
定义函数语法:
def 函数名(形参1,形参2,…) :
函数体(需实现代码)
调用函数:calc
注意:
- 函数名可以包含数字、字幕、下划线,但不能以数字开头。
- 如果函数有返回值,使用 return 关键字
- 定义函数后函数中的代码并不会执行,需要调用函数才会执行
自定义函数
# 定义参数 使用def关键字
def name(num1,num2) : # 其中num值是必选参数,也成为位置参数,调用的时候必须要有,否则报错
num = num1 + num2
return num
#调用
print(name(3,5))
参数类型检查
# 参数类型检查
def my_abs(x):
#可以为函数添加文档注释,也称为文档字符串doc string
# 三个双引号,回车即可自动出现param和return
"""
计算绝对值
:param x: 参数
:return: 返回x的绝对值
"""
# 对参数类型进行检查
if not isinstance(x,(int,float)):
#抛出自定义异常
raise TypeError('参数类型不正确,只能为数值类型')
if x>=0:
return x
else:
return -x #绝对值,负负为正
print(my_abs('str'))
print(help(my_abs))
print(my_abs(666))
print(my_abs(-666))
默认、可变、关键,命名参数
默认参数
默认参数就是带有默认参数的变量!!
如果我们定义2个值 没有定义默认值的话 如果不赋2个值,就会报错,如果设置默认值以后,那个值即使不定义也不会报错,定义以后就会用你定义的值。
方法:变量=n 即可
# 默认参数
# 计算一个值的n次方
def my_pow(x,y=2): #设置y的默认值为2
if y==0:
return 1 #如果输入0,则默认1次方 避免结果为0
res = x # 定义一个x
for i in range(y - 1): # 循环次数,因为上面已经定义一个x了,所以这需要-1
res *= x # 开平方
return res
print(my_pow(2,3))
print(my_pow(2))
可选参数
就是说参数可以想传多少传多少,也就是参数数量是可变的。
方法:变量名(*可选参数)或 变量名(固定参数,*可选参数) 注:可选参数是以数组的形式展现,如果要获取里面的值,需要通过遍历获取!
def my_sus(*x): #单独定义一个 可变参数
print(x)
my_sus(1,2,3,4,5,6) # 以数组方式打印
print('*' * 50)
def my_usu(x,*y): #x是必选参数,y是可选参数
print(x)
print(y)
my_usu(1,4,4,4,5,6,7)
# 也可以调用数组()和[]都可以,方法 *变量名
def my_usu(x,*y): #x是必选参数,y是可选参数
print(x)
print(y)
nums=(1,4,4,4,5,6,7)
my_usu(66,*nums) #*nums等同于,nums[0],nums[1],....
print('*' * 50)
my_usu(66,nums)
如果有必选参数,和 可选参数,建议把必选参数放前面,如果必须参数放后面,需要指定必须变量名再赋值,否则报错
def test(*x,y):
print(x)
print(y)
# test(5,4,5,6,412) 这样赋值会报错,会默认为全部是赋值给x的
test(5,13,3,11,y=66)
关键字参数
使用 ** ,也表示参数个数是可变的,但传递的是带名称的参数。
#关键字参数
def f1(x,**y):
print(x)
print(y)
f1(666,a=6,b=66,c='牛牛牛')
也可以调用字典dict内容,方法和可变参数一样 **变量名
#关键字参数
def f1(x,**y):
print(x)
print(y)
# f1(666,a=6,b=66,c='牛牛牛')
user = {'age':23,'name':'ccx','add':'china'}
f1(666,**user)
# 等同于
f1(555,age=user['age'],name=user['name'],add='china')
命名关键字参数
限制关键字参数的名字,使用* 分割,*号后面的参数表示命名关键字参数。
def f2(x,*,name,age,add): # *没有任何意义,单纯用来分割而已
print(name)
print(age)
print(add)
f2(666,name='ccx',age=23,add='china')
接受任意参数
*args
:接受任意参数**kwargs
:接受任意命名参数
# 任意参数
def f3(*args,**kwargs):
print(args) # 任意参数
print(kwargs)#任意命名参数
f3(666,555,'ccx','....',age=23,name='ccx',add='china',wa='...')
自定义函数
空函数
表示先定义一个空函数,以后实现 自定义功能。
def kong() :
pass # 表示 是空函数,暂不赋值
# 定义函数的返回值,可以定义多个返回值
def f1():
name = 'ccx'
age = 23
sex = 'man'
return name,age,sex
print(f1()) # 返回值是一个tuple(数组)
# 获取数组里面的值
a, b, c = f1() # 任意定义3个参数,按顺序分别对应f1()中的三个参数
print(a, b, c)
函数的返回值,返回一个函数
简单来说 就是调用一个已定义的函数
方法:直接 函数名() 即可
注:如果用print输出变量名,会多一个None
def test(x) :
print('你调用了该函数,并输入了参数'+x)
def kong():
print('你调用了一个空函数')
pass
test(str(666)) # 调用函数
print(test(str(777)),type(test(str(888)))) #输出函数!!!
print('$' * 50)
kong() #调用函数
print(kong()) # 使用输出结果都会多一个None,而调用却不会!
也可以嵌套使用,调用的参数或局部变量成为:闭包
def f1(x):
print('调用了f1')
y = 6 #定义 局部变量
def f2(z): #内部函数(这里属于函数f1)
print(x * y + z) #内部函数使用了外部(f1)函数的参数或局部变量,成为闭包
return f2 #这里返回属于 内部函数(f2)
fn = f1(3) # 定义变量,并给x赋值3
print('....')
fn(5) # 使用函数,这里定义的其实是z,因为调用f1 返回的是内置函数f2的return
递归函数
一个函数在内部调用自身,这个函数就叫做递归函数。
demo:计算x的y次方
普通方法
#普通写法
def f1(x,y):
if y == 0:
return 1 # 平方次数 最少一次,避免报错
i = 1
sum = x
while i<y : # 因为上面定义了一个sum,所以这需要-1
sum *= x
i += 1 #先当于y的+1
return sum
print(f1(2,0)) #直接调用
ff = f1(2,3) #先定义再返回结果
print(ff)
递归函数方法
#递归函数方式
def f2(x,y):
if y==0: #这里是停止条件,如果不定义这个,就会进入死循环
return 1
else:
#递归条件
#2x2x2x2x2=2x(2x2x2x2)=2x(2x(2x2x2))=2x(2x(2x(2x2)))=2x(2x(2x(2x(2x1))))) # 这里的1就是停止条件
return x * f2(x,y - 1) # 不停的调用自己,直到满足y=0停止
print(f2(2,5))
当然,不能太作死的递归自己,否则会栈溢出!
变量作用域和命名空间
变量作用域
变量作用域 scope:指的是变量生效的区域
有两种作用域:
1,全局作用域:函数意外的区域都是全局作用域,在全局作用域中定义的变量,都是全局变量。
2,函数作用域,也称为局部作用域:函数内的区域,每调用一次函数就会创建一个新的函数作用域,在函数作用域中定义的变量,都是局部变量。
变量的查找顺序:先在当前作用域中查找,如果没有则向上一级作用域中查找,直到查找全局作用域,如果还是没有,则报错。
#作用域介绍
a = 666 #全局变量
if True:
b = 777 #全局变量(不在函数内!!!)
# 在python中没有块级作用域(在java中 这里面定义的外面是用不了的)
def f1():
c = 999 #局部变量
print('函数内部:a=',a)
print('函数内部:b=', b)
print('函数内部:c=',c)
f1()
print('——' * 20)
print('函数外部:a=', a)
print('函数外部:b=', b)
# print('函数外部:c=', c)
默认全局变量中的变量名与局部(函数内)变量名没有关系。
a = 10 #全局a
def fn():
a=20 #局部a
print('内部a',a)
print('外部a',a)
fn()
print('——' * 20)
global关键字(局部中让外部生效)
b = 10
def fn2():
#如果想在内部函数中修改全局变量的值,需要使用参数 global关键字来声音变量
global b # 声明这里面的b是全局变量b
b = 20
print('内部b',b)
return b
fn2()
print('外部b',b)
#变量查找介绍
#先在当前作用域中查找,如果没有则向上一级作用域中查找,直到查找全局作用域,如果还是没有,则报错。
x = 1#全局作用域
def f2():
x = 2#上一级作用域
print(x)
def f3():
x = 3#当前作用域
print(x)
命名空间
命名空间namespace
:指的是变量存储的位置,每一个变量都要存储在指定的命名空间中;
每个作用域都有一个对应的命名空间;
全局命名空间,用来存储全局变量;
函数命名空间,用来存储函数中的变量;
命名空间实际上就是一个字典(dict),是一个专门用来存储变量的字典。
获取命名(locals)
使用方法: locals() 获取当前作用域的命名空间
注:在全局中使用就是调用全局命名,在函数中使用并调用函数,就是获取该函数中的命名。
# 命名空间
a = 6
b = 66
scp = locals()
print('全局变量:',scp)
print('参数类型:',type(scp)) # 在全局作用域中调用locals,获取的就是全局命名空间
def f1():
c = 666
print('调用函数:',locals())
f1()
def f2(name) : #设置返回值
age = 23
sc = locals()
print('调用参数函数命名:',sc) #返回一个名字/值对的字典
f2('ccx') #调用并输入返回值
修改命名参数
a = 6
b = 7
print('修改前的总变量:',a,b)
scp = locals()
scp['a'] = 666 # 修改变量a
scp['b'] = 777
print(scp)
print('修改后的总变量:',a,b)
z = 456
def f1():
c = 123
sc = locals()
sc['c'] = 321
sc['z'] = 654 #修改总变量z ,因为查找规则就是先函数后总变量,但仅对当前函数生效
print(sc)
print('函数中修改总变量:',z) # 函数中修改的总变量,不能直接用print打印!
f1()
print('总变量z:',z)
获取命名(globals)
可以在任意位置获取全局命名空间
方法:globals()
a = 6
def f1():
b = 7
scp = globals()
print(scp)
print(scp['a'])
f1()
高级特性(迭代和列表生成式)
迭代
迭代:迭代的意思是重复做一些事很多次,就像在循环中做的那样,也称为遍历,循环获取每一个元素;
- 回忆一下普通遍历:
for i in ('tom','alk','ccx') :
print(i,end=',')
print()
for j in {'name':'ccx' , 'age':'2','ccx':'最帅'}.keys():
print('1:',j,end=',')
print()
for j in {'name':'ccx' , 'age':'2','ccx':'最帅'}.items():
print('2:',j,end=',')
print()
for k,l in {'name':'ccx','age':22,'ccx':'超级cool'}.items() :
print('3:',k,l,end=',')
print()
print('4:',end=' ')
for n in 'good evening' :
print(n,end=',')
- 判断是否可迭代
需要判断对象是否是可迭代的,判断方法:isinstance(file,Collections,Iterable)
——返回布尔类型
print(isinstance('good evening',Collections,Iterable))
- 使用enumerate()函数,转换为索引-元素对
name = {'ccx':'is a hero','age':22}
print(enumerate(name))
print('enumetate函数:',end=' ')
for k,v in enumerate(name):
print(k,v,end=',')
print()
print('普通遍历:',end=' ')
name1 = {'ccx':'is a hero','age':22}
for n,m in name1.items() :
print(n,m,end=',')
- 迭代使用
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter()
和next()
。
迭代器iterator
:用来访问集合元素的一种方式,可以记住迭代的位置。
字符串,列表或元组对象都可用于创建迭代器
迭代的普通用法
# 普通迭代 一次一个值
list = [1,2,3,4]
i = iter(list) #调用iter()函数创建迭代器
print(next(i))# 调用next()函数获取迭代器的下一个元素
print(next(i))
print(next(i))
print(next(i))
迭代器对象可以使用常规for语句进行遍历:
和普通遍历比起来,区别最大的可能就是 逼格更高把??? 或许迭代器只能往前不会后退。虽然知道怎么体现,但看不见的好处或许就是这个把!!!
next使用:因为的我会报错,所以我加了个try机制。没找到原因。
list = [1,2,3,4]
i = iter(list)
while True:
try:
print(next(i))
except StopIteration:
exit()
列表生成式
列表生成式:简单来说,用来创建list的生成式
如: 生成0-99的list
# 普通for循环的方法
for i in range(0,100):
print(i,end=',')
print()
#生成式方法
nums = range(0,100)# 如果转换格式 其实就是个range模式。
print(nums)
print()
nums1 = list(range(0,100)) # 需要转换为list格式,可以直接打印!!!!
print(nums1,end=',')
如:打印1,100之间所有的偶数
如:生成一个包含1-100之间所有3的倍数的list
# 方式一
print('方法一:',end=' ')
lst = range(1,101)
for i in lst:
if i % 3 == 0:
print(i,end=',')
print()
# 方式二
print('方法二:',end=' ')
lst1 = []
for i in range(1,101):
if i%3 == 0 :
print(i,end=',')
print()
#方式三
print('方法三:',end=' ')
lst2 = [i for i in range(1,101) if i%3==0]
print(lst2)
生成器
生成器generator:在循环过程中一次计算获取值的对象;
创建生成器的方式:
方式一:把一个列表生成式的[]改成()
#方式一:把一个列表生成式的[]改成()
generator = (i for i in range(0,100))
print('generator类型为:',type(generator))
# 注意,上面的generator并没有生成值,只有获取时才会生成值
# 获取生成器的下一个值
print(next(generator))
print(next(generator))
print(next(generator))
print(next(generator))
print('*' * 50)
# 遍历generator的值
for i in generator:
print(i,end=',') # 因为0-3上面已经用next获取了,所以这儿不会有0-3
知道迭代特性会记录获取的值,所以如果提取超过值便会抛异常
方式二:在函数中使用yield关键字,此时该函数就变成一个生成器函数
#方式二:在函数中使用yield关键字,此时该函数就变成一个生成器函数
def gen():
print('one')
yield 13
print('two')
yield 8
print('three')
yield 25
print('four')
yield 38
#生成器函数与普通函数的执行流程不一样;
#普通函数是顺序执行,执行到最后一行或者遇到return时结束
#生成器函数是在每次嗲用next时执行,遇到yield语句就返回,下一次调用next()时会从上一次返回的yield语句处继续执行
g = gen()
print(type(g))
print(next(g))
print(next(g))
print(next(g))
print('*' * 50)
#使用for循环遍历生成器
for i in g:
print(i) #从上一个next()返回结果的下一处继续执行!
高阶函数
自定义高阶函数
高阶函数:一个函数接收另一个函数作为参数,这种函数成为高阶函数。
# 定义一个函数,用来检查数字是否大于5
list = [4,5,6,7,8,18, 19, 20, 21, 22, 23, 24,111,112]
def f1(x):
if x > 5:
return True #没有实际作用,只是测试满足x>5就会输出True而已
return False
print('f1条件函数:',f1(6))
print('*' * 59)
#自定义高阶函数,用来过滤列表中的函数
def f2(fun,list):
"""
将列表中所有符合条件的元素筛选出来,返回一个新列表
:param fun: 条件函数
:param list: 要进行筛选的列表
:return: 返回新列表
"""
new_list=[] # 创建一个新列表
for i in list:
if fun(i):
new_list.append(i) #满足条件的添加到列表中
return new_list # 返回新列表
num = f2(f1,list) # 调用f1函数,传入list列表内容
print('f2条件函数:',num)
print('*' * 50)
定义这种高阶函数的好处在于 条件可以随时变更 ,然后调用高阶函数的时候再调用新的条件函数即可,如:上面创建了一个>5的条件函数(f1),一个高阶函数(f2),现在创建一个新的条件(f3)
#自定义高阶函数,用来过滤列表中的函数
def f2(fun,list):
"""
将列表中所有符合条件的元素筛选出来,返回一个新列表
:param fun: 条件函数
:param list: 要进行筛选的列表
:return: 返回新列表
"""
new_list=[] # 创建一个新列表
for i in list:
if fun(i):
new_list.append(i) #满足条件的添加到列表中
return new_list # 返回新列表
num = f2(f1,list) # 调用f1函数,传入list列表内容
print('f2条件函数:',num)
print('*' * 50)
def f3(x):
if x % 2 == 0: # 只要偶数
return True
print('f3条件函数:',f2(f3,list)) #输出并调用 f2高阶函数,传入 函数f3和list列表
内置高阶函数
- 内置高阶函数 filter(),用于过滤序列
使用方法:filter(条件函数,列表)
lst = [4,5,6,7,8,18, 19, 20, 21, 22, 23, 24,111,112]
def f3(x):
if x % 2 == 0: # 只要偶数
return True
num = filter(f3,lst)
print(list(num))
- 内置高阶函数 map(),用于处理序列
使用方法:map(条件函数,列表)
lst = [4,5,6,7,8,18, 19, 20, 21, 22, 23, 24,111,112]
def f4(n):
return n+1
def f5(n):
return n*n
print('原列表:',lst)
print('所有数值+1:',list(map(f4,lst)))
print('所有数值开平方:',list(map(f5,lst)))
- 内置高阶函数 sorted(),用于排序
使用方法:sorted(列表) # 默认排序 小到大
sorted(列表,reverse=True)# 大到小排序
sorted(列表,key=)#key= 是自定义条件,后面也可以加reverse=True
lst = [1,2,3,-55,-100,66] #普通列表
lst1 = [{'a':1,'b':2,'c':3,'d':4}] #多维列表
a = sorted(lst) # 默认排序 从小到大
b = sorted(lst,reverse=True) #从大到小,因为reverse默认为false。
c = sorted(lst,key=abs,reverse=True) #最简单的条件,绝对值排序
d = sorted(lst1,key=lambda n:n,reverse=True)
# d是多维列表的使用方法,按理说 n:n[0]是单独提取不排序,n:n[1]是排序,但我这会报错,不知道为啥。n是自定义的。
print('小到大:',a)
print('大到小:',b)
print('绝对值(大到小):',c)
print(d)
匿名函数和装饰器
匿名函数
匿名函数:没有名字的函数,只能使用一次。
方法:lambda关键字
nums = [3,55,6,22,8]
# 以map为例,让nums列表中值 x2+1
def f1(x):
return x*2+1
a = list(map(f1,nums))
print('f1函数返回结果:',a)
# 假设f1函数只用一次,这么定义一个f1 就显得有点麻烦了,所以可以定义一个 匿名函数
b = list(map(lambda x:x*2+1,nums))
print('匿名函数返回值:',b)
匿名函数除了可以调用列表以外,也可以定义一个匿名函数,然后赋值并调用匿名函数
abc = lambda x:x+5
print(abc(1))
print(abc(555))
装饰器
装饰器:装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能(称为装饰器Decoration,类似于AOP),装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
方法:先定义一个装饰器(其实就 是一个 def函数)
def name():
def new_name():
#功能块
return new_name()
使用:在 需要增加功能的函数上面 @装饰器函数name即可
如:
# 定义一个装饰器,为该函数添加打印日志功能
def log(fn):
def wrapper(*args,**kwargs):
print('开始执行%s()函数。。。'% fn.__name__) # __name__ 内置属性,获取名字
res = fn(*args,**kwargs)
print('执行%s()函数结束。。。' % fn.__name__)
return wrapper() #返回装饰函数
# 随便定义了一个装饰器
。
def abc(a):
def c():
print('this is ...')
return c()
lst = [ 2,3,4,5,6,66,555]
@log
def f1(lst):
for i in lst: #遍历
if i % 2 ==0 : #只要偶数
print(i)
@abc
def f2(num1,num2):
sum = num1+num2 # 计算
return sum # 返回sum
f1(lst)
print('*' * 50)
print(f2(3,5))
注:上面代码运行有报错,方法就是这样使用的,至于为什么运行报错, 现在的我并无法解决,报错如下。
那时的我无法解决,不代表现在的我无法解决(我的博客都是累计到一定数量,然后一并发布)。既然不会 那么就多查资料 多总结多实验嘛 ,单独说下 修饰器