六.函数和类

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()

 

posted @ 2019-03-29 13:44  观井映天  阅读(160)  评论(0编辑  收藏  举报