一、函数:函数是逻辑结构化和过程化的一种编程方法。函数即变量
1:可变参数
#参数组:**字典 *列表 def test(x,*args): print(args); print(args[0]); print("--------"); test(1,2,3,4,5); # (2, 3, 4, 5) # 2 # -------- test(1,[2,3,4,5]); # ([2, 3, 4, 5],) # [2, 3, 4, 5] # -------- test(1,*[2,3,4,5]); # (2, 3, 4, 5) # 2 # -------- def test2(x,**kwargs): print(kwargs); print("--------"); test2(1,y=2,z=3) # {'y': 2, 'z': 3} # -------- def test3(x,*args,**kwargs): print(args); print(kwargs); print("--------"); test3(1,4,5,6,y=2,z=3) # (4, 5, 6) # {'y': 2, 'z': 3} # -------- test3(1,*[4,5,6],**{"y":"2","z":"3"}) # (4, 5, 6) # {'y': 2, 'z': 3} # --------
总结:在python中可以动态的接收参数, *接收位置参数,**来接收动态关键字参数
Default values are computed once, then re-used.默认值参数只被执行1次
2:命名空间与作用域
在python解释器开始执⾏之后, 就会在内存中开辟⼀个空间, 每当遇到⼀个变量的时候, 就把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内存, 表⽰这个函数存在了, ⾄于函数内部的变量和逻辑, 解释器是不关⼼的. 也就是说⼀开始的时候函数只是加载进来, 仅此⽽已, 只有当函数被调⽤和访问的时候, 解释器才会根据函数内部声明的变量来进⾏开辟变量的内部空间. 随着函数执⾏完毕, 这些函数内部变量占⽤的空间也会随着函数执⾏完毕⽽被清空.
#locals() 查看局部作用域内的变量 #globals() 查看全局作用域内的变量 A="全局变量" def part(): b="局部变量" print(locals()) #{'b': '局部变量'} print(globals()) ''' {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0184D250>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Code/AaronScrapy/AaronScrapyCode/test.py', '__cached__': None, 'A': '全局变量', 'part': <function part at 0x0354EF60>} ''' part()
总结:locals() 查看局部作用域内的变量;globals() 查看全局作用域内的变量
b="全局变量" def partB(): b="B作用域变量" print(b) partB() print(b) ''' B作用域变量 全局变量 结论一:各个作用域使用各自区域内的变量, ''' def partC(): b="C作用域变量" def partD(): print(b) partD() print(b) partC() print(b) ''' C作用域变量 C作用域变量 全局变量 结论二:各个作用域使用各自区域内的变量,如果没有,去最近区域内找 ''' def partD(): global b print(b) b="在D作用域中修改" partD() print(b) ''' 全局变量 在D作用域中修改 结论二:global可以把作用域之间的界限打通,直接使用全局能量,如果修改,也会影响全局 ''' b="全局变量" def partE(): b="E作用域变量" def partF(): nonlocal b print(b) partF() print(b) partE() print(b) ''' 全局变量 在D作用域中修改 结论二:nonlocal可以把最近存在该变量作用域之间的界限打通,直接使用该能量,如果修改,直接影响该变量 '''
总结:
- global表⽰. 不再使⽤局部作⽤域中的内容了. ⽽改⽤全局作⽤域中的变量
- nonlocal 表⽰在局部作⽤域中, 调⽤⽗级命名空间中的变量.
- 变量使用遵守就近原则
3:递归函数
递归函数默认深度为999。
def Remainder(num): # 短除法取余数,取到商为0,然后反向输出余数 if(num//2==0): print(num % 2); return ; Remainder(num//2); print(num%2); Remainder(11);
# 定义一个人员数组,记录问路人 person_list=['Aaron','ZhangSan','LiSi','WangWu','YangKe']; # 定义一个问路函数 def ask_way(person_list): # 每循环一次弹出一个人,如果人员数组中值为空,那么表示没有人知道 if len(person_list)==0: return "没人知道"; person = person_list.pop(0); if person == "YangKe": return '%s说:“哦,我知道”' %person; print("hi,[%s],敢问路在何方?" % person); print("[%s]说:“我不知道,我可以帮你问问%s...”" %(person,person_list)); res=ask_way(person_list); print("%s问的结果是:%res" %(person,res)); return res; result = ask_way(person_list); print(result);
# 根据范围获取其中3和7整除的所有数的和,并返回调用者 # 符合条件的数字个数以及符合条件的数字的总和 # 方法一:通过递归调用 def func(start,end,a=0,su=0): if start==end: return a,su if start%3==0 or start%7==0 : a = a + 1; su = su +start; start = start+1 return func(start,end,a,su) resu=func(1,11) print(resu) # 方法二:通过for def func2(start,end,a=0,su=0): for i in range(start,end): if i%3==0 or i%7==0 : a+=1 su+=i return a,su resu=func2(1,11) print(resu)
4:匿名函数
# 格式 lambda x:返回结果 func = lambda x,y,z:x+y+z; print(func(1,2,3))
5:常用函数
5.1 map函数
# 格式map(函数名,可迭代类型) # map函数实现原理 def maptest(func,arr): # 定义一个新的数组 restArray=[]; for i in arr: # 调用传递过来的函数 result = func(i); restArray.append(result); return restArray; #通过lambda表达式调用 serArray=[15,321,54,86,1,5,9,3,5,4,68]; rest=maptest(lambda x:x+1,serArray); print(rest); # 输出结果 [16, 322, 55, 87, 2, 6, 10, 4, 6, 5, 69] rest2 = map(lambda x:x+1,serArray); print(list(rest2)); # 输出结果 [16, 322, 55, 87, 2, 6, 10, 4, 6, 5, 69]
res=map(lambda x,y:x+y,[1,2,3],[4,5,6]) print(list(res)) # [5, 7, 9] res=map(lambda x,y:x+y,[1,2,3],[4,5]) print(list(res)) # [5, 7] def Add(*args): sum = 0 for i in args: sum += i return sum res=map(Add,[1,2,3],[4,5,],[7,8,9]) print(list(res)) # [12, 15]
5.2 filter函数
# 定义一个观看电影人员的列表 movie_people=['a_zhangsan','b_zhangsan','a_lisi','b_lisi']; #定义一个过滤人员的逻辑 def getAPeople(currPeople): return currPeople.startswith("a"); def filterTest(funct,array) : rest = []; for p in array: if funct(p): rest.append(p); return rest; print(list(filterTest(getAPeople,movie_people))); # 输出结果 ['a_zhangsan', 'a_lisi'] # 利用系统自带的filter函数 print(list(filter(lambda x:x.startswith("a"),movie_people))); # 输出结果 ['a_zhangsan', 'a_lisi']
5.3 reduce函数
# 定义一个数据列表 arr = [1,2,3,4,5,6,7,8,9] #定义一个处理逻辑 def getSum(sum,x): return sum+x; # 一共有三个参数:(函数名,可迭代类型,初始值) def reduceTest(fun,array,init=None): if init is None: sum = array.pop(0); else: sum = init; for n in array: sum = fun(sum,n); return sum; print(reduceTest(getSum,arr,100)); #print(reduceTest(getSum,arr)); # 注意 1:这里可以设置一个初始值 # 2:需要导入包 from functools import reduce print(reduce(lambda x,y:x+y,arr,100));
6:内置函数
# 6.1 绝对值 print(abs(-2)); # 输出结果 2 # 6.2 进行布尔运算,一假全假 print(all([1,'0',True])); # 输出结果 True print(all([0,'1',True])); # 输出结果 False # 6.3 进行布尔运算,一真全真 print(any([0,'1',True])); # 输出结果 True # 6.4 进行布尔运算,'' None 0 为false,其余为True print(bool(None)); # 输出结果 False # 6.5 bytes print(bytes("zhang三",encoding="utf-8")); # 输出结果 b'zhangxe4xb8x89' print(bytes("zhang三",encoding="utf-8").decode("utf-8")); # 输出结果 zhang三 # 6.6 ASCII 转化 print(chr(97)); # 输出结果 a # 6.7 dir 查看对象下的方法 print(dir(all)); # 输出结果 ['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__text_signature__'] # 6.8 divmod 分页常用(一共多少条记录,每页多少条记录) print(divmod(101,10)); # 输出结果 (10, 1) # 6.9 eval 很强大 # 6.9.1 将字典类型的字符串转化成字典 dicStr = '{"name":"张三"}'; d1 = eval(dicStr); print(d1['name']); # 输出结果 张三 # 6.9.2 将字符串形式的表达式进行计算 calStr = '1+2*(3+4)'; print(eval(calStr)); # 输出结果 15 # 6.10 hash() 可hash即不可变数据类型 print(hash("张三")); # 输出结果 1381178516053414445 # 6.11 进制转换 print(bin(10));# 10进制==》2进制 # 输出结果 0b1010 print(hex(12));# 10进制==》16进制 # 输出结果 0xc print(oct(12));# 10进制==》8进制 # 输出结果 0o14 # 6.12 判断是否是该类的实例 print(isinstance(1,int)); # 输出结果 True print(isinstance([],list));# 输出结果 True # 6.13 globals(); def test(): age="11"; print(globals()); print(locals()); test(); # 输出结果{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000000527C50>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Code/内置函数.py', '__cached__': None, 'dicStr': '{"name":"张三"}', 'd1': {'name': '张三'}, 'calStr': '1+2*(3+4)'} # 输出结果 {'age': '11'}
# 6.14 zip函数,拉链函数 print(list(zip(('a','b','c'),(1,2,3,4)))) # 输出结果 [('a', 1), ('b', 2), ('c', 3)] p = {'name':'张三','age':15} print(list(zip(p.keys(),p.values()))) # 输出结果 [('name', '张三'), ('age', 15)] # 6.15 最大最小值 # 6.15.1 计算数值列表中的最大值 lis = [1,3,100,-5,50]; print(max(lis));# 输出结果 100 print(min(lis));# 输出结果 -5 # 6.15.2 计算字典中的最大值,并返回姓名 age_dic = {'张三':1,'李四':3,'王五':100,'小刘':-5,'天启':50}; # 方法一 print(max(zip(age_dic.values(),age_dic.keys()))); # 输出结果 (100, '王五') # 方法二 print(max(age_dic,key=lambda key:age_dic[key])); # 输出结果 王五 people = [ {'name':"aaron","age":15}, {'name':"yangKe","age":25}, {'name':"yangXiaoKe","age":27} ]; print(max(people,key=lambda dic:dic["age"])); # 输出结果 {'name': 'yangXiaoKe', 'age': 27} # 6.16 chr与ord print(chr(97)); # 输出结果 a print(ord('a'));# 输出结果 97 # 6.17 pow print(pow(2,3)); # 输出结果 8 print(pow(2,3,2));# 输出结果 0 2**3%2 # 6.18 反转 l=[1,2,3,4] print(list(reversed(l))); # 输出结果 [4, 3, 2, 1] # 6.19 round保留小数位数 print(round(3.141592,5)); # 输出结果 3.14159 # 6.20 set可以用来去重复 print(set('hello')); # 输出结果 {'e', 'o', 'l', 'h'} # 6.21 切片 ll='hello'; s1=slice(3,5); s2=slice(1,4,2); print(ll[s1]); # 输出结果 lo print(ll[s2]); # 输出结果 el # 6.22 sorted 排序 people = [ {'name':"aaron","age":35}, {'name':"yangKe","age":25}, {'name':"yangXiaoKe","age":27} ]; print(sorted(people,key=lambda dic:dic['age'])); # 输出结果 [{'name': 'yangKe', 'age': 25}, {'name': 'yangXiaoKe', 'age': 27}, {'name': 'aaron', 'age': 35}] people2 = [ {"aaron":35, "yangKe":25, "yangXiaoKe":27} ]; print(sorted(zip(people2[0].values(),people2[0].keys()))); # 输出结果 [(25, 'yangKe'), (27, 'yangXiaoKe'), (35, 'aaron')] # 6.23 把其他形式转换成字符串 dic_str=str({"a":"1"}); print(dic_str); # 输出结果 {'a': '1'} print(eval(dic_str));# 输出结果 {'a': '1'} # 6.24 vars def test(): msg="abc"; print(locals()); print(vars()); test(); print(vars(int)); # 输出结果 {'msg': 'abc'} # 输出结果 {'msg': 'abc'} # 输出结果 {'__repr__': <slot wrapper '__repr__' of 'int' objects>, '__hash__': <slot wrapper '__hash__' of 'int' objects>, '__str__': <slot wrapper '__str__' of 'int' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'int' objects>, '__lt__': <slot wrapper '__lt__' of 'int' objects>, '__le__': <slot wrapper '__le__' of 'int' objects>, '__eq__': <slot wrapper '__eq__' of 'int' objects>, '__ne__': <slot wrapper '__ne__' of 'int' objects>, '__gt__': <slot wrapper '__gt__' of 'int' objects>, '__ge__': <slot wrapper '__ge__' of 'int' objects>, '__add__': <slot wrapper '__add__' of 'int' objects>, '__radd__': <slot wrapper '__radd__' of 'int' objects>, '__sub__': <slot wrapper '__sub__' of 'int' objects>, '__rsub__': <slot wrapper '__rsub__' of 'int' objects>, '__mul__': <slot wrapper '__mul__' of 'int' objects>, '__rmul__': <slot wrapper '__rmul__' of 'int' objects>, '__mod__': <slot wrapper '__mod__' of 'int' objects>, '__rmod__': <slot wrapper '__rmod__' of 'int' objects>, '__divmod__': <slot wrapper '__divmod__' of 'int' objects>, '__rdivmod__': <slot wrapper '__rdivmod__' of 'int' objects>, '__pow__': <slot wrapper '__pow__' of 'int' objects>, '__rpow__': <slot wrapper '__rpow__' of 'int' objects>, '__neg__': <slot wrapper '__neg__' of 'int' objects>, '__pos__': <slot wrapper '__pos__' of 'int' objects>, '__abs__': <slot wrapper '__abs__' of 'int' objects>, '__bool__': <slot wrapper '__bool__' of 'int' objects>, '__invert__': <slot wrapper '__invert__' of 'int' objects>, '__lshift__': <slot wrapper '__lshift__' of 'int' objects>, '__rlshift__': <slot wrapper '__rlshift__' of 'int' objects>, '__rshift__': <slot wrapper '__rshift__' of 'int' objects>, '__rrshift__': <slot wrapper '__rrshift__' of 'int' objects>, '__and__': <slot wrapper '__and__' of 'int' objects>, '__rand__': <slot wrapper '__rand__' of 'int' objects>, '__xor__': <slot wrapper '__xor__' of 'int' objects>, '__rxor__': <slot wrapper '__rxor__' of 'int' objects>, '__or__': <slot wrapper '__or__' of 'int' objects>, '__ror__': <slot wrapper '__ror__' of 'int' objects>, '__int__': <slot wrapper '__int__' of 'int' objects>, '__float__': <slot wrapper '__float__' of 'int' objects>, '__floordiv__': <slot wrapper '__floordiv__' of 'int' objects>, '__rfloordiv__': <slot wrapper '__rfloordiv__' of 'int' objects>, '__truediv__': <slot wrapper '__truediv__' of 'int' objects>, '__rtruediv__': <slot wrapper '__rtruediv__' of 'int' objects>, '__index__': <slot wrapper '__index__' of 'int' objects>, '__new__': <built-in method __new__ of type object at 0x000007FEF26161E0>, 'conjugate': <method 'conjugate' of 'int' objects>, 'bit_length': <method 'bit_length' of 'int' objects>, 'to_bytes': <method 'to_bytes' of 'int' objects>, 'from_bytes': <method 'from_bytes' of 'int' objects>, '__trunc__': <method '__trunc__' of 'int' objects>, '__floor__': <method '__floor__' of 'int' objects>, '__ceil__': <method '__ceil__' of 'int' objects>, '__round__': <method '__round__' of 'int' objects>, '__getnewargs__': <method '__getnewargs__' of 'int' objects>, '__format__': <method '__format__' of 'int' objects>, '__sizeof__': <method '__sizeof__' of 'int' objects>, 'real': <attribute 'real' of 'int' objects>, 'imag': <attribute 'imag' of 'int' objects>, 'numerator': <attribute 'numerator' of 'int' objects>, 'denominator': <attribute 'denominator' of 'int' objects>, '__doc__': "int([x]) -> integer int(x, base=10) -> integer Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating point numbers, this truncates towards zero. If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int('0b100', base=0) 4"} # 6.24 import import say say.sayHello(); # 输出结果 Hello module_name="say"; m=__import__(module_name); m.sayHello(); # 输出结果 Hello
7:Python函数传参是传值还是传引用
def change(val): val=10 nums = 1 change(nums) print(nums) #输出结果为 1 def change(val): val.append(100) val = ['x', 'y', 'z'] nums = [0, 1] change(nums) print(nums) #输出结果为【0,1,100】
Python中函数参数的传递是传递的变量的值,即就是变量所指向的对象的地址。
一般的,我们有下面的规律:
1. 不可变对象作为函数参数,相当于C系语言的值传递。
2. 可变对象作为函数参数,相当于C系语言的引用传递。
3.一旦函数中遇到=,就会重新开辟一个内存空间,不再对传递过来的参数有影响
8:练习
a = 1 # 执行顺序 1 def fun_1(): # 执行顺序 2 a = 2 # 执行顺序 5 def fun_2(): # 执行顺序 6 nonlocal a # 执行顺序 9 注意:nonlocal用法是获取最近区域的a值。也就是第三行a等于2 a = 3 # 执行顺序 10 注意:此时修改同时修改第三行a。等于3 def fun_3(): # 执行顺序 11 a = 4 # 执行顺序 14 print(a) # 执行顺序 15 输出:4 print(a) # 执行顺序 12 输出:3 fun_3() # 执行顺序 13 print(a) # 执行顺序 16 输出:3 print(a) # 执行顺序 7 输出:2 fun_2() # 执行顺序 8 print(a) # 执行顺序 17 输出:3 print(a) # 执行顺序 3 输出:1 fun_1() # 执行顺序 4 print(a) # 执行顺序 18 输出:1 ''' 1 2 3 4 3 3 1 '''
# 1*2*3*4*5*6*7=5040 # 方法一 利用递归实现 def getCul(start,end,cul=1): cul = cul * start if start==end: return cul start=start+1 return getCul(start,end,cul) print(getCul(1,7)) # 方法二 利用递归实现 def f(n): if n==1: return 1 return n*f(n-1) print(f(7)) # 方法三 利用for循环实现 def getCul2(start,end): cul = 1 for i in range(start,end): cul = cul * i return cul print(getCul2(1,8)) # 注意range方法顾头不顾尾 # 方法四 利用reduce和lambda表达式 from functools import reduce print(reduce(lambda x,y :x*y,[x for x in range(1,8)]))
def addList(par,list=[]): list.append(par) return list l1=addList(11) l2=addList(22,[]) l3=addList("33") print(l1) print(l2) print(l3) ''' [11, '33'] [22] [11, '33'] '''