1.自定义函数
- 给函数编写文档:
def function(x): "This is function document test." #注意这里没有加入#号,这是函数内的写作方式。 pass
#注意下面的语句是function而不是function()。前者表示函数本身,后者表示函数的使用。 print(function.__doc__) help(function)
- 所有的函数都有返回值。函数return后什么都没有,或没有return,函数返回None。不要让None的返回值给你带来麻烦。
2.函数参数
- 函数参数中的中括号[]表示可选参数,可选参数通常都这么写,用的时候别带中括号。:
- L.index(value [, start [, stop ] ] ),这里的中括号表示:start和stop是可选参数。
- 编写代码时,为了确保参数的正确性。应该在参数输入不对时以显而易见的方式失败。为此,通常使用assert断言和raise异常。
- 参数为不可变参数:string、数、tuple,函数不修改外部变量
N=456 def test(n): n=123 test(N) #这相当于函数内部变量先建立内存n=N,然后再处理n print(N) #456
- 参数为可变参数:list、dict,函数修改。
list1=[1,"a",2] def test(l1): l1.append(123) test(list1) #由于是可变参数,l1=list1只是建立了指针,并没有为数据重新建立内存。 print(list1) #[1, 'a', 2, 123]
-
函数参数可以分为位置参数和关键字参数。
- 位置参数具有顺序依赖性
- 关键字参数若以keyword形式传递,可以打乱顺序。function(key2=...,key1=...)
- 参数的收集,输入的参数以什么形式存放:
#参数收集:*args以元组形式存放,**kwargs以字典形式存放 def func(*args,**kwargs): print(args) print(kwargs) func(1,2,3,"a","b",key1="name",key2="age",key3="sex") #(1, 2, 3, 'a', 'b') #{'key1': 'name', 'key2': 'age', 'key3': 'sex'}
-
参数的分配,如果不是一一对应的输入参数,而是输入一个整体,输入数据如何分配:
#如果以序列形式分配,要加上* def test1(a,b,c,d): print(a,b,c,d) List1=[1,"a",2,"b"] Tuple1=(4,3,2,1) test1(*List1) #1 a 2 b test1(*Tuple1) #4 3 2 1 #如果以字典形式分配,要加上**,且key相同 def test2(m,n): print(m,n) Dict1={"m":"name","n":"age"} test2(**Dict1) #name age
3.函数的作用域和嵌套:
- global声明全局变量,nonlocal声明非全局的上一层变量:
#以下例子只是说明问题 , 实际应用中务必慎用全局变量。 x,y,z=1,2,3 def testA(): global x #全局变量,指向最外层 x,y,z=10,20,30 #全局x重新赋值 print("first:",x,y,z) # first: 10 20 30 def testB(): global y #指向最外层,不是上一层 y+=10 #所以y不是上一层的10,而是最外部的2 x=20 #第二层没有声明x,所以x是局部 print("second:",x,y,z) # second: 20 12 30 def testC(): nonlocal x x+=10 global z print("third:",x,y,z) # third: 30 12 3 testC() print("second2:",x,y,z) # second2: 30 12 30 testB() print(testA(),x,y,z) # None 10 12 3
- 函数的嵌套:可以在函数中定义函数,注意嵌套时return的是函数的运行(带括号)还是函数本体(不带括号)
def test1(): def test2(): print("test2 in test1") return test2() #返回的是函数test2()的运行 test1() # test2 in test1 def test3(): def test4(): print("test4 in test3") return test4 #返回的是函数test4的本体 test3()() # test4 in test3,其中的test3()就相当于test4,所以需要加()才可以运行
4.类变量和实例化变量:
- 类分为类变量和实例化变量:
class A: a=123 #类变量 def function(self): self.var1=456#实例化变量,self让各def彼此不独立,self指向某个实例:ca=A(),self指向的就是ca,同时无需提供self指向的参数。 A.var2=456#在功能中定义类变量:实例化且调用此功能才有。 var3=789 #在函数中定义变量 ca=A() print(A.a) #123 ca.function() print(A.a,A.var2) #123 456 cb=A() print(cb.a,cb.var2) #123 456,由于类被改变,再次新的实例会有
- 类操作和实例操作,实例中先扫描实例变量,后扫描类变量:
class TEST: test="ABC" pass #t.***为实例化操作 #TEST.***为类操作 t=TEST() t.test="DEF" #实例化操作,单变量赋值等同于定义 print(t.test) #DEF,先扫描到实例化结果 del t.test #删除了实例化结果 print(t.test) #ABC,扫描到类变量
- 类变量和实例变化更具体的操作:
class TEST: a=123 #类变量 CommonList=[] def __init__(self): TEST.var="ABC" #这表示,创建实例时,增加类变量TEST.var="ABC" TEST.a+=10 self.mylist = [] #print(TEST.a,TEST.var) #无法执行,因为没有增加进去 A=TEST() B=TEST() print(TEST.a,A.a,B.a) print(TEST.var,A.var,B.var) TEST.var="abcdef" print(TEST.var,A.var,B.var) A.a=A.a+10 #单变量在赋值时,等于自定义语句 print(A.a,B.a,TEST.a) #类中增加类变量 TEST.b="ADD" print(TEST.b,A.b,B.b) #实例a中增加self.a变量 A.a=456 print(TEST.a,A.a,B.a) #实例中,先索引实例变量,再类变量 #删除实例a中的self.a变量,但是依然有类变量a del A.a print(TEST.a,A.a,B.a) #mylist操作,实例操作 A.mylist.append("MyA") B.mylist.append("MyB") print(A.mylist,B.mylist) #CommonList操作,直接操作。实例中并没有增加,而是对类列表的操作 A.CommonList.append("add a") B.CommonList.append("add b") TEST.CommonList.append("add TEST") print(A.CommonList,B.CommonList,TEST.CommonList) #实例中增加列表 A.NewList=[] A.NewList.append("NewListA") print(A.NewList) #实例中增加列表且与类列表同名 A.CommonList=[] print(A.CommonList,B.CommonList,TEST.CommonList) del A.CommonList print(A.CommonList,B.CommonList,TEST.CommonList)
- 函数或类带()表运行,不带()表它本身的代码:var=ABC() 不同于 var=ABC
5.类中设置私有化变量
- Python不同于C++,类中没有专门的public、private。
- 若类中要有私有化成员:__双下划线打头,访问需要特殊化访问:
class TEST: __var1=123 #双下划线设置了私有化,无法正常访问 a=TEST() print(a._TEST__var1) #以此方式才可以访问私有化 print(TEST._TEST__var1) #同上
-
from module import * 不会导入一个下划线打头的名称
- 若类中要有私有化成员:__双下划线打头,访问需要特殊化访问:
6.lambda函数,快速的表达函数:
- lambda表达式:lambda ...(输入)... : ...(输出)...
#下面两句表达效果一样,都把函数关联到变量foo def foo(x):return x*x foo=lambda x:x*x
7.装饰器
# 装饰器:本质是函数,为给其他函数添加附加功能 # 原则:1.不能修改被装饰函数的源代码 # 2.不能修改被装饰函数的调用方式 # 实现装饰器知识储备: # 1.函数即“变量” # 2.高阶函数 # a:把一个函数名当做实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加功能) # b:返回值中包含函数名(不修改函数的调用方式) # 3.嵌套函数 # 高阶函数+嵌套函数=>装饰器 import time def timmer(func): def warpper(*args,**kwargs): start_time=time.time() func() stop_time=time.time() print("the func run time is %s" %(stop_time-start_time)) return warpper #注意这里不是warpper() @timmer def test1(): time.sleep(1) print("in the test1") test1()