一. 函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,定义一个函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。函数内容以冒号起始,并且缩进。return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。#语法def 函数名(参数1,参数2,参数3,...): '''注释''' 函数体 return 返回的值#函数名要能反映其意义
def auth(user:str,password:str)->int: if user == '111' and password == '111': return 1# print(auth.__annotations__) #{'user':, 'password': , 'return': }user=input('用户名>>: ').strip()pwd=input('密码>>: ').strip()res=auth(user,pwd)print(res)
1.函数使用的原则:先定义,再调用
函数即“变量”,“变量”必须先定义后引用。未定义而直接引用函数,就相当于在引用一个不存在的变量名#测试一def foo(): print('from foo') bar()foo() #报错#测试二def bar(): print('from bar')def foo(): print('from foo') bar()foo() #正常#测试三def foo(): print('from foo') bar() def bar(): print('from bar')foo() #会报错吗?#结论:函数的使用,必须遵循原则:先定义,后调用#我们在使用函数时,一定要明确地区分定义阶段和调用阶段#定义阶段def foo(): print('from foo') bar()def bar(): print('from bar')#调用阶段foo()
2.return 语句
return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。之前的例子都没有示范如何返回数值,以下实例演示了 return 语句的用法:
# 定义函数def printme(str): "打印任何传入的字符串" print(str) return str# 调用函数aa=printme("我要调用用户自定义函数!");bb=printme("再次调用同一函数");print(aa)print(bb)
a#!/usr/bin/python3 # 可写函数说明def sum( arg1, arg2 ): # 返回2个参数的和." total = arg1 + arg2 print ("函数内 : ", total) return total # 调用sum函数total = sum( 10, 20 )print ("函数外 : ", total)
2.参数传递 (值传递 引用传递)
参数传递分为: 值传递: string tuple number 是不可变 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。def ChangeInt( a ): a = 10 b = 2ChangeInt(b) #a==bprint b # 结果是 2
引用传递:传递的可变类型 list dict set 是可变的 可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。# 可写函数说明def changeme( mylist ): "修改传入的列表" mylist.append([1,2,3,4]); print "函数内取值: ", mylist return # 调用changeme函数mylist = [10,20,30];changeme( mylist );print "函数外取值: ", mylist函数内取值: [10, 20, 30, [1, 2, 3, 4]]函数外取值: [10, 20, 30, [1, 2, 3, 4]]
3.关键字参数
关键字参数
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。以下实例在函数 printme() 调用时使用参数名:关键字参数关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。以下实例在函数 printme() 调用时使用参数名:#可写函数说明def printinfo( name, age ): "打印任何传入的字符串" print "Name: ", name; print "Age ", age; return;#调用printinfo函数printinfo( age=50, name="miki" );#可写函数说明def printme( str ): "打印任何传入的字符串" print str; return;#调用printme函数printme( str = "My string");
4. 默认参数
调用函数时 如果没有传递参数就是使用默认参数 如果传递了参数就不使用默认参数
def ChangeInt( a=1,b=2 ): c=a+b return cChangeInt()print (c) # 3def ChangeInt( a=1,b=2 ): c=a+b return cChangeInt(12,10)print (c) # 22# 要使用默认参数 最好将默认参数放到最后def ChangeInt( a,b=2 ): c=a+b return cChangeInt(12)print (c) # 14
# 调用函数时,缺省参数的值如果没有传入,则被认为是默认值。下例会打印默认的age,如果age没有被传入:#!/usr/bin/python# -*- coding: UTF-8 -*- #可写函数说明def printinfo( name, age = 35 ): "打印任何传入的字符串" print "Name: ", name; print "Age ", age; return;#调用printinfo函数printinfo( age=50, name="miki" );printinfo( name="miki" );以上实例输出结果:Name: mikiAge 50Name: mikiAge 35
5.不定长数()
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。
不定长参数你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。基本语法如下:def functionname([formal_args,] *var_args_tuple ): "函数_文档字符串" function_suite return [expression]
# 加了星号(*)的变量名会存放所有未命名的变量参数。不定长参数实例如下:# 可写函数说明def printinfo( arg1, *vartuple ): "打印任何传入的参数" print (arg1) print(*vartuple) for var in vartuple: print (var) return;printinfo( 10 );printinfo( 70, 60)
# 可写函数说明def printinfo( arg1, *vartuple ): "打印任何传入的参数" print "输出: " print arg1 for var in vartuple: print var return;# 调用printinfo 函数printinfo( 10 );printinfo( 70, 60, 50 );
# 加了星号(*)的变量名会存放所有未命名的变量参数。不定长参数实例如下:# 可写函数说明def aa(name,*age): print(name) #张三 for i in age: print(i)#25 28 23 20aa("张三",25,28,23,20)
# **是代表键值对的传参方式 和*代表的意义一样def aa(*arg,**name): print(arg) print(name) #{"a":1,"b":2,"c":3S} print(type(name)) #{"class" dict}aa(55,66,77,a=1,b=2,c=3,d=4)# (55, 66, 77)# {'a': 1, 'b': 2, 'c': 3, 'd': 4}#
二.匿名函数
python 使用 lambda 来创建匿名函数。
lambda只是一个表达式,函数体比def简单很多。lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。语法
lambda函数的语法只包含一个语句,如下:lambda [arg1 [,arg2,.....argn]]:expressio语法lambda函数的语法只包含一个语句,如下:lambda [arg1 [,arg2,.....argn]]:expression# 可写函数说明sum = lambda arg1, arg2: arg1 + arg2;# 调用sum函数print "相加后的值为 : ", sum( 10, 20 )print "相加后的值为 : ", sum( 20, 20 )# 相加后的值为 : 30# 相加后的值为 : 40
aa=lambda a,b :a+b;print(aa(5,6))# 可写函数说明# sum = lambda arg1, arg2: arg1 + arg2;dic={ 'a1':20,'a2':566,'a3':60}def di(key): return dic[key]cc=max(dic,key=di)print(cc)print(max(dic,key=lambda k :dic[k]))res=filter(lambda x:x>10,[12,5,6,36])print(res)for i in res: print(i)# a=lambda p:p*2# b=lambda p:p*3# x=2# x=a(x)#4# x=b(x)#12# x=a(x)#24## print(x)# 转换成字典# (('a'),('b')),(('c'),('d'))ret=zip((('a'),('b')),(('c'),('d')))def du(tup): return {tup[0]:tup[1]}gig=map(du,ret)aa=list(gig)print(aa)# 匿名函数常用的内置函数 zip filter map max min stor storedret=zip((('a'),('b')),(('c'),('d')))gig=map(lambda tup:{tup[0]:tup[1]},ret)aa=list(gig)print(aa)
a=22,66print(a)# (22, 66)f1=lambda x,y:x,6print(f1)# 匿名函数返回多个值后面必须加上括号 因lambda前面是一部分 后面是一部分fn=lambda x,y:(x,y)aa=fn(22,66)print(aa)bb=lambda x,y:max(x,y)print(bb(55,99))bb=lambda *args:max(args)print(bb(55,99,55,888,77))
三 . 变量作用域
一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。两种最基本的变量作用域如下:全局变量局部变量全局变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称total = 0; # 这是一个全局变量# 可写函数说明def sum( arg1, arg2 ): #返回2个参数的和." total = arg1 + arg2; # total在这里是局部变量. print "函数内是局部变量 : ", total return total; #调用sum函数sum( 10, 20 );print "函数外是全局变量 : ", total # 把局部变量改成全局变量name=111110000000000000000000def AA(): global name # global 意思就是把局部变量改成全局变量 name=2220000 print(name)AA()print(name)
1.把局部变量改成全局变量global
# 把局部变量改成全局变量name=111110000000000000000000def AA(): global name # global 将全局变量 变成局部变量 name=2220000 print(name) # 2220000AA()print(name) # 2220000"""1、global---将变量定义为全局变量。可以通过定义为全局变量,实现在函数内部改变变量值。2、一个global语句可以同时定义多个变量,如 global x, y, z"""# 注意: 如果函数的内容global 关键字 优先读取局部变量 只能读取全局变量 无法重新赋值#注意函数中有global 关键字 变量本质上就是全局的那个变量 可以赋值
a='张三'def aa(): global a print('您好',a) # 您好 张三 a='李四' print('lover',a) # lover 李四def bb(): a=111111 print('这是',a) # 这是 111111aa()bb()
global 声明了使用全局的变量a=1def aa(): a=6 def bb(): b=2 print(a) # 这里是取最近的a def cc(): global a # global 声明了使用全局的变量 print(a) a+=1 print(a) cc() bb() print(a)aa()print("全局",a)
# 6 # #.bb at 0x000002043621E9D8> # # cc函数 # # 用nonlocal 声明了一个上层的局部变量 7 # # # 全局
2.nonlocal 声明了一个上层的局部变量
# nonlocal 声明了一个上层的局部变量a=1def aa(): a=6 def bb(): b=2 print(a) print(bb) def cc(): nonlocal a # nonlocal 声明了一个上层的局部变量 最近一个 有a的变量 a+=1 print("cc函数") cc() bb() print("用nonlocal 声明了一个上层的局部变量",a)aa()print("全局",a)
3. locals作用返回字典类型的局部变量。
# locals作用返回字典类型的局部变量。def f(): print(locals()) #作用域内无变量 b = 5555 print(locals()) #作用域内有一个a变量,值为1f()print(locals())
# {} # {'b': 5555} # {'__name__': '__main__', '__doc__': None, '__package__': # None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002099440D208>, '__spec__': # None, '__annotations__': {}, '__builtins__':, '__file__': 'D:/老男孩教育/test.py', '__cached__': None, 'f': }
4.globals() 函数会以字典类型返回当前位置的全部全局变量
# globals() 函数会以字典类型返回当前位置的全部全局变量a=1b=2c=3print(globals())#{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':# <_frozen_importlib_external.SourceFileLoader object at 0x0000029468BBD208>, '__spec__': None, '__annotations__':# {}, '__builtins__':, '__file__': 'D:/老男孩教育/test.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3}