Python函数基础
1. Python中函数的概念
1.1 python中函数概念
Python中函数是逻辑结构化和过程化的一种编程方法。
1.2 python中函数定义方法解释
python中函数定义方法: def test(x): "The function definitions" x+=1 return x def:定义函数的关键字 test:函数名 ():内可定义形参 "":文档描述(非必要,但是强烈建议为你的函数添加描述信息) x+=1:泛指代码块或程序处理逻辑 return:定义返回值 调用运行:可以带参数也可以不带 函数名()
# def test(x,y,z):#x=1,y=2,z=3 # print(x) # print(y) # print(z) #位置参数,必须一一对应,缺一不行多一也不行 # test(1,2,3) #关键字参数,无须一一对应,缺一不行多一也不行 # test(y=1,x=3,z=4) #位置参数必须在关键字参数左边 # test(1,y=2,3)#报错 # test(1,3,y=2)#报错 # test(1,3,z=2) # test(1,3,z=2,y=4)#报错 # test(z=2,1,3)#报错 # def handle(x,type='mysql'): # print(x) # print(type) # handle('hello') # handle('hello',type='sqlite') # handle('hello','sqlite') # def install(func1=False,func2=True,func3=True): # pass #参数组:**字典 *列表 def test(x,*args): print(x) print(args) # test(1) # test(1,2,3,4,5) # test(1,{'name':'alex'}) # test(1,['x','y','z']) # test(1,*['x','y','z']) # test(1,*('x','y','z')) # def test(x,**kwargs): # print(x) # print(kwargs) # test(1,y=2,z=3) # test(1,1,2,2,2,2,2,y=2,z=3) # test(1,y=2,z=3,z=3)#会报错 :一个参数不能传两个值 def test(x,*args,**kwargs): print(x) print(args,args[-1]) print(kwargs,kwargs.get('y')) # test(1,1,2,1,1,11,1,x=1,y=2,z=3) #报错 # test(1,1,2,1,1,11,1,y=2,z=3) # test(1,*[1,2,3],**{'y':1})
1.3 函数和过程
过程定义:过程就是简单特殊没有返回值的函数
def test01(): msg='hello girl' print msg def test02(): msg='hello word' print msg return msg t1=test01() t2=test02() print 'from test01 return is [%s]' %t1 print 'from test02 return is [%s]' %t2
总结:当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,
所以在python中即便是过程也可以算作函数。
def test01(): pass def test02(): return 0 def test03(): return 0,10,'hello',['aaa','bbbb'],{'ccccc':'bbbb'} t1=test01() t2=test02() t3=test03() print 'from test01 return is [%s]: ' %type(t1),t1 print 'from test02 return is [%s]: ' %type(t2),t2 print 'from test03 return is [%s]: ' %type(t3),t3
总结:
返回值的数量=0:返回None
返回值的数量=1:返回object
返回值的数量>1:返回tuple
1.4 Python中函数的好处
1.代码重用
2.保持一致性,易维护
3.可扩展性
2. 局部变量和全局变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
name='xyz' def change_name(): print('我的名字',name) change_name() def change_name(): name='帅' print('我的名字',name) change_name() print(name) def change_name(): global name name='帅' print('我的名字',name) change_name() print(name)
3. 函数即变量(理解函数的一种方法)
def action(): print 'in the action' logger() action() 报错NameError: global name 'logger' is not defined def logger(): print 'in the logger' def action(): print 'in the action' logger() action() def action(): print 'in the action' logger() def logger(): print 'in the logger' action()
4. 嵌套函数和作用域
举例如下:
name = "aaaaa" def change_name(): name = "aaaaa2" def change_name2(): name = "aaaaa3" print("第3层打印",name) change_name2() #调用内层函数 print("第2层打印",name) change_name() print("最外层打印",name)
此时,在最外层调用change_name2()会出现报错;因为作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变。
例一: name='aaa' def loo(): name='bbb' def car(): print(name) return bar kkk=loo() kkk() 例二: name='aaa' def loo(): name='bbb' def car(): name='ccc' def hh(): print(name) return hh return car uuu=loo() uuu()()
5. 递归调用函数
在函数内部,可以调用其他函数。如果在调用一个函数的过程中直接或间接调用自身本身
def calc(n): print(n) if int(n/2) ==0: return n return calc(int(n/2)) calc(10) 输出: 10 5 2 1
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
尾递归优化:http://egon09.blog.51cto.com/9161406/1842475
6. 匿名函数
#正常函数的写法 def test(x): y = x**2 return y #匿名函数的写法 lamada x:x**2
7. 函数式编程
7.1 高阶函数
满足俩个特性任意一个即为高阶函数
1.函数的传入参数是一个函数名
2.函数的返回值是一个函数名
7.2 map函数
array=[1,3,4,71,2] ret=[] for i in array: ret.append(i**2) print(ret) #如果我们有一万个列表,那么你只能把上面的逻辑定义成函数 def map_test(array): ret=[] for i in array: ret.append(i**2) return ret print(map_test(array)) #如果我们的需求变了,不是把列表中每个元素都平方,还有加1,减一,那么可以这样 def add_num(x): return x+1 def map_test(func,array): ret=[] for i in array: ret.append(func(i)) return ret print(map_test(add_num,array)) #可以使用匿名函数 print(map_test(lambda x:x-1,array)) #上面就是map函数的功能,map得到的结果是可迭代对象 print(map(lambda x:x-1,range(5))) map函数
7.3 filter函数
#电影院聚集了一群看电影bb的傻逼,让我们找出他们 movie_people=['alex','wupeiqi','yuanhao','sb_alex','sb_wupeiqi','sb_yuanhao'] def tell_sb(x): return x.startswith('sb') def filter_test(func,array): ret=[] for i in array: if func(i): ret.append(i) return ret print(filter_test(tell_sb,movie_people)) #函数filter,返回可迭代对象 print(filter(lambda x:x.startswith('sb'),movie_people)) filter函数
7.4 reduce函数
from functools import reduce #合并,得一个合并的结果 array_test=[1,2,3,4,5,6,7] array=range(100) #报错啊,res没有指定初始值 def reduce_test(func,array): l=list(array) for i in l: res=func(res,i) return res # print(reduce_test(lambda x,y:x+y,array)) #可以从列表左边弹出第一个值 def reduce_test(func,array): l=list(array) res=l.pop(0) for i in l: res=func(res,i) return res print(reduce_test(lambda x,y:x+y,array)) #我们应该支持用户自己传入初始值 def reduce_test(func,array,init=None): l=list(array) if init is None: res=l.pop(0) else: res=init for i in l: res=func(res,i) return res print(reduce_test(lambda x,y:x+y,array)) print(reduce_test(lambda x,y:x+y,array,50)) reduce函数
7.5 总结
#当然了,map,filter,reduce,可以处理所有数据类型 name_dic=[ {'name':'alex','age':1000}, {'name':'wupeiqi','age':10000}, {'name':'yuanhao','age':9000}, {'name':'linhaifeng','age':18}, ] #利用filter过滤掉千年王八,万年龟,还有一个九千岁 def func(x): age_list=[1000,10000,9000] return x['age'] not in age_list res=filter(func,name_dic) for i in res: print(i) res=filter(lambda x:x['age'] == 18,name_dic) for i in res: print(i) #reduce用来计算1到100的和 from functools import reduce print(reduce(lambda x,y:x+y,range(100),100)) print(reduce(lambda x,y:x+y,range(1,101))) #用map来处理字符串列表啊,把列表中所有人都变成sb,比方alex_sb name=['alex','wupeiqi','yuanhao'] res=map(lambda x:x+'_sb',name) for i in res: print(i) 总结
函数数编程更多请参考:
https://www.cnblogs.com/linhaifeng/articles/6113086.html#_label10
http://egon09.blog.51cto.com/9161406/1842475
8. 内置函数
内置函数详解:https://docs.python.org/zh-cn/3/library/functions.html?highlight=built#ascii
#取绝对值 # print(abs(-1)) # print(abs(1)) #检查多个元素的结果是否为true,有一个为false则为false #特殊情况:只有一个空元素时为true # print(all([1,2,'1'])) # print(all([1,2,'1',''])) # print(all('')) #检查多个元素的结果是否为true,有一个为True则为True # print(any([0,''])) # print(any([0,'',1])) #十进制转换为二进制 # print(bin(3)) #判断布尔值结果:空,None,0的布尔值为False,其余都为True # print(bool('')) # print(bool(None)) # print(bool(0)) #编码解码 # name='你好' # print(bytes(name,encoding='utf-8')) # print(bytes(name,encoding='utf-8').decode('utf-8')) # # print(bytes(name,encoding='gbk')) # print(bytes(name,encoding='gbk').decode('gbk')) # # print(bytes(name,encoding='ascii'))#ascii不能编码中文 #判断某个变量有哪些具体变量组成 # print(dir(dict)) #计算商数和余数,用来判断某个内容需要多少页 # print(divmod(10,3)) #提取字符串中的数字结构 # dic={'name':'alex'} # dic_str=str(dic) # print(eval(dic_str)) #可hash的数据类型即不可变数据类型,不可hash的数据类型即可变数据类型 # print(hash('12sdfdsaf31231dfasdfasdfasdfasdfasdfasfasfdasdf')) #打印某内置函数的使用帮助 # print(help(all)) #进制转换 # print(bin(10))#10进制->2进制 # print(hex(12))#10进制->16进制 # print(oct(12))#10进制->8进制 #查看内存地址 name = xyz print(id(name)) #判断某个内容是否是被判断的类型 # print(isinstance(1,int)) # print(isinstance('abc',str)) # print(isinstance([],list)) # print(isinstance({},dict)) # print(isinstance({1,2},set)) #显示全局变量详细信息 name='哈哈哈哈哈哈哈哈哈' # print(globals()) # print(__file__) # #显示局部变量详细信息 # def test(): # age='111111111111111111111111111111111111111111' # # print(globals()) # print(locals()) # # test()
#取最大值和最小值 # l=[1,3,100,-1,2] # print(max(l)) # print(min(l)) # #拉链函数,将元素1和元素2分别对应组成新的元素对 # print(list(zip(('a','n','c'),(1,2,3)))) # print(list(zip(('a','n','c'),(1,2,3,4)))) # print(list(zip(('a','n','c','d'),(1,2,3)))) # # p={'name':'aaaa','age':18,'gender':'none'} # print(list(zip(p.keys(),p.values()))) # # print(list(p.keys())) # # print(list(p.values())) # # print(list(zip(['a','b'],'12345'))) age_dic={'a_age':18,'w_age':20,'z_age':100,'l_age':30} # print(max(age_dic.values())) # # #默认比较的是字典的key # # print(max(age_dic)) # # for item in zip(age_dic.values(),age_dic.keys()): # print(item) # # print('=======>',list(max(zip(age_dic.values(),age_dic.keys())))) # l=[ # (5,'e'), # (1,'b'), # (3,'a'), # (4,'d'), # ] # # l1=['a10','b12','c10',100] #不同类型之间不能进行比较 # l1=['a10','a2','a10'] #不同类型之间不能进行比较 # print(list(max(l))) # print('--->',list(max(l1))) # # l=[1,3,100,-1,2] # print(max(l)) # dic={'age1':18,'age2':10} # print(max(dic)) #比较的是key # print(max(dic.values())) #比较的是values,但不知是哪个key对应的 # print(max(zip(dic.values(),dic.keys()))) #结合zip使用 # #MAX终极用法 # people=[ # {'name':'a','age':1000}, # {'name':'w','age':10000}, # {'name':'y','age':9000}, # {'name':'l','age':18}, # ] # print(max(people,key=lambda dic:dic['age'])) #MAX的用法类似于这个原理: # ret=[] # for item in people: # ret.append(item['age']) # print(ret) # max(ret) #关于ASCII码,chr通过索引找字符,ord通过字符找索引 # print(chr(97)) # print(ord('a')) # print(pow(3,3)) #3**3 # print(pow(3,3,2)) #3**3%2 #按照相反的顺序排序 # l=[1,2,3,4] # print(list(reversed(l))) # print(l) #四舍五入 # print(round(3.5)) #设置集合 # print(set('hello')) #设置切片取值的范围和步长 # l='hello' # s1=slice(3,5) # s2=slice(1,4,2) # # print(l[3:5]) # print(l[s1]) # print(l[s2]) # print(s2.start) # print(s2.stop) # print(s2.step) #sorted按照从小到大进行排序 # l=[3,2,1,5,7] # l1=[3,2,'a',1,5,7] # print(sorted(l)) # # print(sorted(l1)) #排序本质就是在比较大小,不同类型之间不可以比较大小 # people=[ # {'name':'a','age':1000}, # {'name':'w','age':10000}, # {'name':'y','age':9000}, # {'name':'l','age':18}, # ] # print(sorted(people,key=lambda dic:dic['age'])) # name_dic={ # 'ab': 11900, # 'al':1200, # 'wu':300, # } # print(sorted(name_dic)) # # print(sorted(name_dic,key=lambda key:name_dic[key])) # # print(sorted(zip(name_dic.values(),name_dic.keys()))) #type查看数据类型 # print(str('1')) # print(type(str({'a':1}))) # dic_str=str({'a':1}) # print(type(eval(dic_str))) #sum求和 # l=[1,2,3,4] # print(sum(l)) # print(sum(range(5))) # # # print(type(1)) # # msg='123' # # if type(msg) is str: # msg=int(msg) # res=msg+1 # print(res) # #VAR不带参数和locals一样,带一个参数是以字典的形式显示该参数的功能 # def test(): # msg='未来日记勒韦尔' # print(locals()) # print(vars()) # test() # print(vars(int)) #import是引入模块的函数 #import------>sys----->__import__() # import test # test.say_hi() #如果要引入字符串类型的模块,就需要_import_引入 # import 'test'#报错 # module_name='test' # m=__import__(module_name) # m.say_hi()
感谢林海峰老师的博客支持,本章引用非常多,再次感谢!
原博地址:https://www.cnblogs.com/linhaifeng/articles/6113086.html#_label10