Day3 - Python基础3 函数基本、递归函数、内置函数
本节内容
1. 函数基本语法及特性
2. 参数与局部变量
2.2. 函数变量作用域
3. 返回值
嵌套函数
4.递归
5.匿名函数
6.函数式编程介绍
7.高阶函数
8.内置函数
1. 函数基本语法及特性
函数是什么?
函数的英文 function()功能的意思。(即一般一个函数实现一个功能) 函数的作用: 1.减少重复代码 2.方便修改,更易扩展 3.保持代码的一致性
函数语法定义:
def 函数名(形参): ... 函数体 ... 返回值 函数名(实参) ---------我是分割线------- def add(a,b) c = a+b return c add(12+34)
2. 参数与局部变量
形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量;
实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值;
形参的种类3种:
#def test(a,b,c=3): # print(a,b,c) #普通参数,必须一一对应,缺一不行多一也不行 # test(1,2,3) #默认参数,无须一一对应,缺一不行多一也不行 # test(y=1,x=3,z=4) 注意:默认参数必须在关键字参数左边,传入则覆盖,不传则是默认c=3 #test(1,2) -----------分割线--------------------- ##可变参数 *args 变成了() **kwargs 变成了{} def test(a,*args,**kwargs): print(a) ##1 print(args,args[1]) ##(2, 4, 3) 4 print(kwargs,kwargs.get('y')) ##{'c': 45, 'y': 23} 23 ##第一种实参传入 #test(1,2,4,3,y=23,c=45) ##第二种实参传入,*l1 和 **d1 叫做分解参数,变成第一种参数传入的方式 l1 = [2,4,3] d1 = {'y':23,'c':45} test(1,*l1,**d1)
局部变量:LEGB原则
name = "Alex Li" def change_name(name): print("before change:",name) name = "金角大王,一个有Tesla的男人" print("after change", name) change_name(name) print("在外面看看name改了么?",name) 输出: before change: Alex Li after change 金角大王,一个有Tesla的男人 在外面看看name改了么? Alex Li
全局与局部变量:
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。 全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。 当全局变量与局部变量同名时: 在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
2.2 函数变量作用域 LEGB原则
LEGB是指python中命名空间的四个从低到高不同的层次,分别是Local , Enclosing , Global , Built-in。local指一个函数或者方法的内部的空间,enclosing指的是闭包内部空间,global是整个脚本的全局空间,而built-in是指python最上层的系统自带的一些名字的空间。
因为python可以提供这么多不同层次的命名空间,所以当我们在程序中写下一个变量名的时候,解释器就会通过一定的顺序来查找这个变量名的具体内容。这个顺序显然就是local --> enclosing --> global --> built-in。如果按照此顺序逐级而上却没有找到相关的变量名的内容的话就表明这个变量名在哪一级命名空间中都不存在,程序就会raise起一个NameError了。
name = 'crik' #G def func(): name = 'crik2' #E def outer(): #L name = 'crik3' print(name) print(name) outer() print(name) func() 输出: crik crik2 crik3
3. 返回值
return的作用
1:结束函数 2:返回某个对象 这个对象可以是任意的!
1 def add(*args): 2 sum = 0 3 for i in args: 4 sum += i 5 print(sum) 6 # return sum 7 8 a = add(1,3) 9 print(a)
结果:
4 注意:这里的4是函数的print的,一般来说;调用函数后要保存下来结果是吧?
None 而你没有return语句,那么就回默认返回一个None:所以一定要记得return
强行插入知识点: 嵌套函数
def outer(): print('outer') def inner(): print('inner') return inner ##这里return的是inner的内存地址,所以需要再次的调用, ##要是没有return inner的话,print('inner')永远不会被输出,因为别人调用不到! q = outer() q() ##再次调用
4.递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
def fb(a,b): if a == 0 and b ==1: print(a) if b >300: return else: print(b) a,b = b,a+b return fb(a,b) fb(0,1) 输出: 0 1 1 2 3 5 8 13 21 34 55
5.匿名函数
匿名函数的作用:
1:省空间 (定义了函数,而里面的函数体一直等着别人去引用【一直在内存里面呆着】,而匿名则是用一次,就自动消除了)
2:没有函数名
知识点:定义个 name = 'crik' 我们说name这个变量指向了 ‘crik’这个的内存地址,而我们也可以把函数名等同与指向了函数体的内存地址的变量!
#这段代码 def calc(n): return n**n print(calc(10)) #换成匿名函数 calc = lambda n:n**n print(calc(10))
你也许会说,用上这个东西没感觉有毛方便呀, 。。。。呵呵,如果是这么用,确实没毛线,改进,不过匿名函数主要是和其它函数搭配使用的呢,如下
res = map(lambda x:x**2,[1,5,7,4,8]) for i in res: print(i)
输出
1
25
49
16
64
6.函数式编程介绍
7.高阶函数
变量可以指向函数,函数的参数能接收变量:那么一个函数就可以接收另一个函数作为参数:这种函数就称之为高阶函数。
def add(x,y,f): return f(x) + f(y) #abs是一个内置的函数 res = add(3,-6,abs) print(res)
8. 内置参数
内置函数eval
内置函数:eval >>> s = input('plz input something:') ##input输入默认是字符串的 plz input something:[1,2,3,4] >>> s '[1,2,3,4]' >>> s.[0] SyntaxError: invalid syntax >>> s = eval(s) ##把字符串当中的数据结构提取出来 >>> s[0] 1 >>> >>> eval('1-23-4-5') ##还能把字符串当中的表达式给你执行下 -31 >>>
内置函数isinstance、issubclass
isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() isinstance(obj, Foo) ##输入 True issubclass(sub, super)检查sub类是否是 super 类的派生类 class Foo(object): pass class Bar(Foo): pass issubclass(Bar, Foo) ##输出True
内置函数zip
>>> v = [(1,'qwq'),(3,'rt'),(2,'yu')] ##有这个一组列表,我想要获取[1,2,3]的格式 >>> zip(*v) <zip object at 0x00000000028EF608> ##默认python3 zip之后生成迭代器 >>> list(zip(*v)) ##采用list迭代出来 [(1, 3, 2), ('qwq', 'rt', 'yu')] >>> list(zip(*v))[0] (1, 3, 2) >>>
内置函数ord、chr、bin
###输出字符在ASCII码中的位置 >>> ord('A') 65 >>> ord('5') 53 ##将数字按ASCII码的位置输出对应的字符 >>> chr(53) '5' >>> chr(65) 'A' >>> >>> bin(23) ##将数据变成二进制 '0b10111'
内置函数__import__
通过字符串的形式,导入模块。起个别名 ccas。 comm = input("Please:") ccas = __import__(comm) ccas.f1() # 需要做拼接导入时后加 fromlist=True(否则只导入lib) ccas = __import__("lib."+comm, fromlist=True) 3:单例模式
内置函数round
>>> round(4.6) ##四舍五入 5 >>>
内置函数map
map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list, 并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。 例如,对于list [1, 2, 3, 4, 5, 6, 7, 8, 9] 如果希望把list的每个元素都作平方,就可以用map()函数: >>> l=[1,2,3,4,5,6,7] >>> result = map(lambda x:x**x,l) >>> result <map object at 0x0000000002900240> ##这是个迭代器 >>> list(result) ##可以直接采用list进行遍历 [1, 4, 27, 256, 3125, 46656, 823543] 在后面的Django框架中: 我们可能获取一个values_list的列表元组数据格式,要组成一个字典:这里就简单的做个样子 >>> l=[(1,'q'),(2,'r'),(4,'t')] >>> result = map(lambda x:{"id":x[0],"name":x[1]},l) >>> result <map object at 0x0000000002900320> >>> list(result) [{'id': 1, 'name': 'q'}, {'id': 2, 'name': 'r'}, {'id': 4, 'name': 't'}] 上文的zip函数,复习下。这个也很重要,后面会用到。 >>> l [(1, 'q'), (2, 'r'), (4, 't')] >>> list(zip(*l)) [(1, 2, 4), ('q', 'r', 't')] >>> list(zip(*l))[0] (1, 2, 4) >>>
练习:4个随机字符串 由数字和大小写组成
import random num_0 = ord('0') num_9 = ord('9') num_a = ord('a') num_z = ord('z') num_A = ord('A') num_Z = ord('Z') n = 0 chat = '' while n <4: ##ascii 是 0-256个 i = random.randrange(0,256) if i in range(num_0,num_9+1): ##默认range顾头不顾尾 temp = chr(i) ##如果是0-9的ascii对应的数字,就转为字符 相加 chat += temp n +=1 #n+1 用于判断什么时候退出循环 elif i in range(num_A,num_Z+1): temp = chr(i) chat += temp n +=1 elif i in range(num_a,num_z+1): temp = chr(i) chat += temp n +=1 else: pass else: print('generate success...') print(chat) 输出:67Az