函数是实现特定功能的代码段的封装,在需要的时候可以多次调用函数来实现该功能。
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 关键字定义函数后函数中的代码并不会执行,需要调用函数才会执行
默认参数就是带有默认参数的变量!! 如果我们定义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)命名空间namespace:指的是变量存储的位置,每一个变量都要存储在指定的命名空间中; 每个作用域都有一个对应的命名空间; 全局命名空间,用来存储全局变量; 函数命名空间,用来存储函数中的变量; 命名空间实际上就是一个字典(dict),是一个专门用来存储变量的字典。
使用方法: 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()
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列表匿名函数除了可以调用列表以外,也可以定义一个匿名函数,然后赋值并调用匿名函数
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))注:上面代码运行有报错,方法就是这样使用的,至于为什么运行报错, 现在的我并无法解决,报错如下。
那时的我无法解决,不代表现在的我无法解决(我的博客都是累计到一定数量,然后一并发布)。既然不会 那么就多查资料 多总结多实验嘛 ,单独说下 修饰器,参见:https://blog.csdn.net/cuichongxin/article/details/106563876