zoukankan      html  css  js  c++  java
  • 函数(匿名函数,嵌套函数,高阶函数,装饰器)

    函数:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需要调用其函数名即可。

    特性: 减少重复代码  是程序变的可扩展   是程序变得易维护

    函数参数:

    参数可以让你的函数变得跟灵活,不只你能做死循环的动作,还可以根据调用时传参的不同来决定函数内部的执行流程

    形参变量

    只有在被调用的时候才分配内存单元,,在调用结束时,即可释放所分配的内存单元,因此,形参只在函数内部有效,函数调用结束返回主调用函数后则不能再使用该形参变量

    实参

    可是常量,变量,表达式,函数等,无论实参是何种类型的量,再进行函数调用时,他们都必须有确定的值,以便把这些值传送给形参。

    Def calc(x,y):    x,y  形参

    Res = x**y

    Retrun res

    C = calc(a,b)    a,b  实参

    默认参数必须要放在位置参数的后边。     def function(name ,age ,course,city=’北京’)

    关键参数 def function(name,age,course=’py’,country=‘cn’)      function(’张鉴’,course=’py’,age=22,country=’KOR’)

     非固定参数   -- 方式一 以元祖形式的

    def send_alert(msg,*args):    #*之后的可以有很多同类型的参数,打包成元祖,例如账户邮箱等
    
        for u in args:
            print('warning!!!',u,msg)
    send_alert('error!!','pig','ccn','zj')
    

      

    非固定参数  -- 方式二                          非固定参数必须放在最后习惯

    uz = ['pig','ccn','zj']
    def send_alert(msg,*user):
        for u in user:
            print('warning!!!',u,msg)
    send_alert('error!!',*uz)

    传字典 就用**

    def func(name,*args,**kw):   #**is dic  -zidian
        print(name,args,kw)
    dic = {'ccn':'zj'}
    func('alex',22,'mashaladi','50w',addr='shandong',num=31344141,**dic) 

    函数-返回值

    函数外部的代码想要获取函数执行的结果,就可以在函数里用return语句把结果返回

    retrun 代表一个函数的结束 ,只要碰到retrun就结束,后边有多少代码都不执行了

    函数-局部变量

    指定义在函数里边的变量   ,只能在局部生效,函数一点执行结束,变量就消失了在内存里

    定义在函数顶层的一级代码的变量,为全局变量。全局变量,全部代码都可以调用

    如果想在函数中使用修改全局变量可以使用global     --  不建议使用,一般情况下不用

    函数-函数中修改列表中的数据

    names = ['dogs','Black','pigs']
    def change_name():
        #global names
        del names[2]
        names[1] = 'Write'
    
        names = [‘123’,’465’]     #这个是不可以修改的,如果想要修改就要加上global
        print(names)
    change_name()
    print(names)

    函数-嵌套函数

    def func1():
        print('xdd')
    
        def func2():
            print('dogs')
        func2()
    func1( )

    函数要想执行 必须被调用

    函数-作用域

    在Python中一个函数就是一个作用域,局部变量其实就是放在作用域中

    代码写完之后作用域就生成了,无论函数在哪里调用了,被如何调用了,都会回到最初定义的地方进行向上查找。

    函数- 匿名函数  lambda

    def calc(x,y):
        if x > y:
            return x**y
        else:
            return x/y
    func = lambda  x,y:x**y if x < y else x/y    #shengming  anonymous function
    
    print(func(3,3))
    print(calc(3,3))

    函数-高阶函数

    变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数

    可以将函数当做一个函数参数传进来就是高阶函数

    只需要满足任意一个条件,即是高阶函数 1.接收一个或多个函数作为输入参数2.return 返回另外一个函数

    递归介绍 --递归与栈的关系

    递归就是在函数的执行过程中调用自己

    def recursion(n):
    
        #  sum(n)
        print(n)
        recursion(n+1)
    
    recursion(1)

    递归的作用:可以解决一些复杂的数学问题,例如斐波那契,汉诺塔

    递归的特点:

    1.必须有一个明确的结束条件,否则就会变成死循环,最终撑爆系统内存

    2.每次进入更深的一次递归时,问题规模相比上次递归都应有所减少

    3.递归执行效率不高,递归层次过多会导致栈溢出

    求阶乘

    def factorial(n):
        
        if n == 1:
            return 1
        return n * factorial(n-1)
    
    print(factorial(10))

    尾递归优化:

    只保留一层函数的栈数据,他的当前层不需要等待上一层的结果,而是当前层就需要当前层的数据,但是在Python中即使你写了尾递归的优化也是没有用的,Python还是会给你保留上千次的递归。但是要明白概念,C语言是有这种优化的。

    def cal(n):
        print(n)
        return cal(n+1)
    
    cal(1)

    内置函数 built-in function

    abs  求绝对值

    all # return True 例如列表中,可能有none,0,all会遍历列表(数据结构)所有元素,只要有一个FALSE,就会显示false

    any   与all 相反,只要有一个True  就是True

    ascii   返回一个字符的ascii的值

    bin   返回一个整数的二进制格式

    bool   判断一个数据结构是True or FALSE  bool([]) 空列表、集合、元祖、字典就是FALSE  

    bytearray   # 把byte变成bytearray,可修改的数组

    bytes   # bytes(“中国”“utf-8”)        

    callable   # 判断一个对象是否可以调用,面向对象用的

    chr      #返回一个数字的ascii字符,   比如char(97) 返回就是a

    Delattr   # 面向对象用的

    dir     返回一个对象可调用,操作的属性,功能

    divmod     #返回除法的商和余数

    enumerate  # 返回列表的索引和元素,比如 d = [“alex”,”jack”],enumerate(d) 之后得到(0,”alex”)(1,”jack”)

    eval   # 可以把字符串形式的list,dict,set等,转换成原有的数据类型

    exec  # 把字符串格式的代码 ,进行解释并执行,比如exec("print('hello world')"), 就是解释成print(‘hello world’)  并执行

    exit  # 退出程序

    filter  #对list、dict、set等可迭代的对象进行过滤 ,filter(lambda x: x>10, [1,2,3,4,56,66,77,9,10]),过滤出所有大于10的值   list(filter(lambda x:x > 10,[1,2,3,45,5,5,6,7,77]))        [45, 77]

    frozenset      #将一个集合变成只读

    globals    #打印全局作用于里的值,全局变量

    hash   #  hash函数

    hex    #返回一个10进制的16进制表现形式  例如hex(10) 返回’0xa’

    id    #查看对象内存地址

    isinstance  #判断一个数据结构的类型 isinstance(a,list) a是数据,list是数据类型     True

    map  #list(map(lambda x:x**2,a))         a是列表  map类似于filter

    max   # 求最大值  max(a)

    min   # 求最小值

    Object  #面向对象用

    oct    #8进制数

    ord   #  返回acsii的字符对应的10进制数 ord(‘a’) 返回97

    reversed    #可以将列表翻转 和list.reverse()  功能一样  

    round     #可以把小数四舍五入成整数

    Sum   # 求和   a=[1,2,3]  sum(a)   6

    Zip #   a= [1,2,3]   b = ['a','b','c']     list(zip(a,b))  [(1, 'a'), (2, 'b'), (3, 'c')]

    名称空间 name spase

    Name space  ,顾名思义就是存放名字的地方    举例说明: 变量 x=1 ,1存放于内存中,那名字x存放在哪里呢?名称空间正式存放名字x与1绑定关系的地方。

    Python名称空间有4中 :LEGB

    Locals: 函数内部的名字空间,局部变量

    Enclosing function:在嵌套函数中外部函数的名字空间,如果fun2嵌套在fun1里,对fun2来说,fun1的名字空间就是enclosing

    Globals :当前的模块空间,模块就是一些py文件,也就是说,globals()类似全局变量

    _builtins_:内置模块空间,也就是内置变量或内置函数的名字空间,存放内置方法之类的

    不同变量的作用域不同就是由这个变量所在的名称空间决定的。

    闭包现象

    def closure():
        name = "alex"
    
        def inner():
            print("inner",name)
        return inner
    
    func = closure()   # retrun inner mem address
    
    func()

    由于name变量被inner函数调用着,名称空间得不到释放,所以在函数外也可以被调用,这种情况情况叫做闭包

    函数进阶:装饰器 ,又称语法糖

    在不改变源代码和调用方式的情况下扩展一些新的功能:例如加上认证的模式

    # -*- coding:utf-8 -*-
    
    account = {
        'is_auth' : False,
        'alex' : '123',
        'jack' : 'abc'
    }
    
    def login(func):
        def inner():
            if account['is_auth'] is False:
                username = input('username>>').strip()
                password = input('password>>').strip()
                if username in account :
                    if password == account[username]:
                        print('welcome')
                        account['is_auth'] = True
                        func()
                    else :
                        print('password is error ,please try again')
                else:
                    print('username  not found ')
            else:
                print('user already login')
                func()
        return  inner
    def home():
        print("---home page---")
    
    @login
    def tencent():
        #login()
        print('---tencetn---')
    
    def alibaba():
        print("---alibaba---")
    @login
    def jingdong():
        #login()
        print("---jingdong---")
    
    home()
    tencent = login(tencent) #这里存放的就是inner的内存地址,inner实现了闭包,不会执行里边的func()
    #print(tencent)
    jingdong = login(jingdong)
    
    tencent()
    jingdong()

    列表生成式

    现有个需求,现有列表 a = [1,2,3,4,5,6]  要求你把列表里的每一个值加1.  如何是实现

    a = [1,2,3,4,5,6775,9]

    a = [i+1 for i in a]   # list_builder   列表生成器
    print(a)

    生成器 -- generator

    g = (x * x for x in range(10))
    for i in g:
        print(i)

    函数生成器

    # -*- coding:utf-8 -*-
    
    def febonacci(n):
        a = 0
        b = 1
    
        count = 0
        while count < n:
            tmp = a
            a = b
            b = tmp + b
            #print(b)
            yield b   #  暂停 return
            count +=1
    f = febonacci(20)
    print(next(f))
    print(next(f))
    print(next(f))
    print(next(f))

    用生成器实现并发编程

    # -*- coding:utf-8 -*-
    
    # def g_test():
    #     while True:
    #         n = yield
    #         print("receive from outside:",n)
    #
    # g = g_test()
    # g.__next__()     # 调用生成器,同时会发送None到yield
    #
    # for i in range(10):
    #     g.send(i)        # 调用生成器,同时发送i
    
    # 通过生成器实现多并发效果,线程就是cpu的执行的任务单元
    # 吃包子 c1,c2,c3 消费者
    # 生产者 product
    
    
    def cosumer(name):
        print("comsumer %s ready eat "%name)
        while True:
            baozi = yield
            print("comsumer %s start eat num:%s"%(name,baozi))
    
    c1 = cosumer("c1")
    c1.__next__()
    c2 = cosumer("c2")
    c2.__next__()
    c3 = cosumer("c3")
    c3.__next__()
    
    for i in range(10):
        print("we product %s times baozi"%i)
        c1.send(i)
        c2.send(i)
        c3.send(i)

    迭代器

    我们已经知道,可以直接作用于for循环的数据类型有以下几种:

    1.一类是集合数据类型,如list、tuple、dict、set、str等

    2.一类generator,包括生成器和带yield的generator function。

    这些可直接作用于for循环的对象是否是iterable,可得带的意思就是可遍历、可循环。

    可以使用isinstance()判断一个对象是否是Iterable对象。

    迭代器 几乎等同于 生成器

  • 相关阅读:
    解决跨域问题 cors~ JSONP~
    session,cookie,sessionStorage,localStorage的区别~~~前端面试
    数据库索引的理解
    script的按需加载
    es6 笔记
    JS 工具函数
    JS Error
    数组方法重写:forEach, map, filter, every, some, reduce
    JS: GO 和 AO
    立即执行函数
  • 原文地址:https://www.cnblogs.com/zjaiccn/p/12909662.html
Copyright © 2011-2022 走看看