三. 函数
Python内置了很多函数,可以直接调用。
借助抽象,我们不必关注底层的东西,直接在更高层次上思考问题。
""" 函数名称其实是指向一个函数对象的引用,完全可以把函数名赋值给另一个变量,相当于给这个函数起一个别名。 """ a = abs print(a(-1))#1 #print(a("a"))#TypeError: bad operand type for abs(): 'str' #print(a(1,2))#TypeError: abs() takes exactly one argument (2 given)
定义函数
def my_abs(x): if x>=0: return x else: return -x print(my_abs(-10))#10 """ 一旦执行return,结束程序 在xx.py文件目录下,打开python解释器,可以from yy import xx """ def nop(): pass#占位符,编程时使用 def my_abs(x): if not isinstance(x, (int,float)):#数据类型检查 raise TypeError("错误的操作类型") #print(my_abs("qo")) """ Traceback (most recent call last): File "D:/untitled1/base.py", line 18, in <module> print(my_abs("qo")) File "D:/untitled1/base.py", line 17, in my_abs raise TypeError("错误的操作类型") TypeError: 错误的操作类型 """ def asd(x,y): return x,y#多值返回,仍为单值(tuple) x,y = asd(1,2) z = asd(3,6) print(x,y,z)#1 2 (3, 6)

""" 把参数名字和位置确定下来,函数接口定义就完成了。 调用者无需了解函数内部的复杂逻辑,只需知道如何传递正确参数,以及函数返回值即可。 """ #位置参数, def power(x, n): s = x**n return s s = power(3,3)#调用函数时,传入的值按照先后位置顺序依次赋给参数x,n print(s)#27 #默认参数 def power1(x, n=2): s = x**n return s s1 = power1(3,4) s2 = power1(3) print(s1,s2) #必选参数在前,默认参数在后;变化大的参数在前,变化小的参数在后(可作为默认参数); #降低函数调用的难度,只有与默认参数不同的函数调用才需提供额外的信息; def enroll(name, gender, age=9, city="bj"): print(name,gender,age,city) print(enroll("w","T")) print(enroll("w","r",10)) print(enroll("w","w",city="tj")) """ w T 9 bj None w r 10 bj None w w 9 tj None """ def add_end(L=[]): L.append("END") return L print(add_end())#['END'] print(add_end())#['END', 'END'] def add_end(L=None): if L is None: L=[] L.append("END") return L print(add_end())#['END'] print(add_end())#['END'] #定义默认参数牢记一点:默认参数必须指向不变对象!(编程时,可以设计一个不变对象,尽量设计成不变对象) #可变参数,参数数量不定 def cals(*num):#用tuple方式接收 sum = 0 for n in num: sum = sum + n return sum print(cals(1,2)) print(cals()) l = [1,2,4,3] print(cals(*l))#将l转为可变参数传入 """ 3 0 10 """
""" 关键字参数 可变参数允许传入0-n个参数,这些参数在函数调用时自动组装为一个tuple, 关键字参数允许传入0-n个含参数名的参数,这些参数在函数调用时自动组装为一个dict, """ def person(name,age,**kw): print("name",name,"age",age,"other:",kw) person("n",1) person("w",2,city="bj") ex = {"city":"jn","job":"working"} person("z",3,**ex) #**ex表示把ex这个dict的所有键值对用关键字参数传入到函数的**kw参数,注意kw获得是一个拷贝 #对于可变参数,默认为tuple,本身不可变类型,无需考虑拷贝问题 """ name n age 1 other: {} name w age 2 other: {'city': 'bj'} name z age 3 other: {'city': 'jn', 'job': 'working'} """ """ 命名关键字参数 """ #命名关键字参数需要一个特殊分隔符*,*后面的参数视为命名关键字参数,否则系统无法识别位置参数和命名关键字参数 def child(name,age,*,city="heb",job): print(name,age,city,job) child("j",24,city="bj",job="en")#j 24 bj en,必须传入参数名 child("s",2,job="wer")#s 2 heb wer 命名关键字参数可以有缺省值 #若含有可变参数,之后尾随的命名关键字参数无需* def child1(name,age,*args,city,job): print(name,age,args,city,job) child1("j",24,26,"wzc",city="bj",job="en")#j 24 (26, 'wzc') bj en
""" 参数组合: 顺序必须为:必选参数、默认参数、可变参数、命名关键字参数和关键字参数 """ def f1(a,b,c=0,*args,**kw): print("a=",a,"b=",b,"c=",c,"args=",args,"kw=",kw) def f2(a,b,c=0,*,d,**kw): print("a=",a,"b=",b,"c=",c,"d=",d,"kw=",kw) f1(1,2)#a= 1 b= 2 c= 0 args= () kw= {} f1(1,2,3)#a= 1 b= 2 c= 3 args= () kw= {} f1(1,2,wzc="w")#a= 1 b= 2 c= 0 args= () kw= {'wzc': 'w'} f1(1,2,3,4,"w",x=99)#a= 1 b= 2 c= 3 args= (4, 'w') kw= {'x': 99} f2(1,2,d=99,ext=None)#a= 1 b= 2 c= 0 d= 99 kw= {'ext': None} args = [12,3,4,6] kw = {"x":23} f1(*args,**kw)#a= 12 b= 3 c= 4 args= (6,) kw= {'x': 23} args = [12,3,4,] kw = {"d":23,"x":23} f2(*args,**kw)#a= 12 b= 3 c= 4 d= 23 kw= {'x': 23} """ 任意函数,都可通过func(*args,**kw)形式调用,但不要同时使用太多组合,否则接口理解性差; """

""" def fact(n): if n == 1: return 1 return n*fact(n-1) print(fact(5))#120 递归,逻辑简单清晰,过深的调用会导致栈溢出。 针对尾递归优化的语言可以通过尾递归防止栈溢出。 python的解释器没有针对尾递归做优化。 """ """ 高级特性 """ #切片 """ L = ["w",1,2,2.3,True] print(L[0:3],L[:3])#['w', 1, 2] ['w', 1, 2],取前n个元素 print(L[-2:],L[-2:-1])#[2.3, True] [2.3] L1 = list(range(100)) #取出前10个和后10个 print(L1[:10],L1[-10:])#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [90, 91, 92, 93, 94, 95, 96, 97, 98, 99] print(L1[11:20])#前11-20 print(L1[:10:2])#前10个,每2个取一个 print(L1[::5])#全部,每5个取一个 print(L1[:])#复制 print((0,1,2,3,4)[:3])#(0, 1, 2) print("abcdefg"[::2])#aceg """ #迭代 #给定一个list 或者tuple,for循环遍历,这种遍历我们称为迭代(Iteration) #python的for循环,可以用在其他可迭代对象上dict等 """ d = {"a":1,"b":2,"c":3} for key in d: print(key) a b c dict迭代的结果顺序可能不一样; 默认迭代key """ """ for v in d.values(): print(v) 迭代value 1 2 3 """ """ for k,v in d.items(): print(k,v) 迭代k和v a 1 b 2 c 3 """ """ for c in "abc": print(c) a b c """ #for循环只要作用于一个可迭代对象,包括我们自定义的,只要符合迭代条件,就可以正常运作 #判断迭代对象方法 """ from collections import Iterable print(isinstance("abc",Iterable))#True print(isinstance(123,Iterable))#False for i,value in enumerate(["y","z","w"]): print(i,value) 0 y 1 z 2 w enumerate把一个list变成索引-元素对 """ """ for tu in enumerate(["y","z","w"]): print(tu) (0, 'y') (1, 'z') (2, 'w') """ """ for x,y in [(2,3),[4,5]]: print(x,y) 2 3 4 5 """ #列表生成式,List comprehensions,快速生成list """ print(list(range(5,7)))#[5, 6] L = [] for x in range(3): L.append(x*x) print(L) #[0, 1, 4] print([x*x for x in range(3)])#[0, 1, 4] #生成的元素放前面,后面跟for循环 print([x*x for x in range(4) if x%2 == 0])#[0, 4] print([x+y for x in range(3) for y in [3,4,5]])#[3, 4, 5, 4, 5, 6, 5, 6, 7] import os #查看当前目录索引文件和文件夹(目录) print([d for d in os.listdir(".")])#['.idea', 'CNN.py', 'test', 'test-all', 'test-s', 'test.py', 'testdemo', 'train', 'train-all', 'train-s', 'traindemo', 'valid', 'valid-all', 'valid-s'] d = {"w":2,"z":1,"c":2} print([k+"="+str(v) for k,v in d.items()])#['w=2', 'z=1', 'c=2'] L = ["HeK","EwO123","23","IBM"] print([s.lower() for s in L])#['hek', 'ewo', 'ibm'] L = ["HeK","EwO123","23","IBM",12] print(s.lower() for s in L if isinstance(s,str)) #<generator object <genexpr> at 0x0000020FFF5CCFC0> print([s.lower() for s in L if isinstance(s,str)])#['hek', 'ewo123', '23', 'ibm'] """ #生成器 #内存限制,列表容量有限,generator,生成器,可以一边循环,一边计算后续元素 #创建generator第一种方法,[列表生成式]--->(列表生成式) g = (x for x in range(4)) print(g)#<generator object <genexpr> at 0x000001844C31AA40> """ for n in g: print(n) 0 1 2 3 """ while True: try: g1 = next(g) print(g1) except StopIteration as e: print("end") break """ 1 2 3 end """ #第二种方法,函数实现 def fib(max): n,a,b = 0,0,1 while n<max: print(b) a,b = b,a+b#厉害 n = n+1 return "done" print(fib(3)) """ 1 1 2 done """ #fib函数定义了推算规则,逻辑是从第一个元素推算后续任意的元素 def fib(max): n,a,b = 0,0,1 while n<max: yield b#将print变成yield a,b = b,a+b#厉害 n = n+1 return "done" print(fib(3))#列表生成式 <generator object fib at 0x0000020A4E153620> #若函数定义中包含yield,函数变成generator,每次调用next时候执行,遇到yield返回,再次执行从上次返回的field语句继续执行 for n in fib(6): print(n) """ 1 2 3 5 8 拿不到generator的return语句值 """ g = fib(6) while True: try: x = next(g) print(x) except StopIteration as e: print("return:",e.value) break """ 1 1 2 3 5 8 return: done """ """ python,可以简单的把列表生成式改成generator,也可以通过函数实现复杂的generator generator工作原理:for循环过程中不断计算下一个元素 函数式的generator,遇到return或者执行到函数最后一行,即结束for循环 """
浙公网安备 33010602011771号