• 第三章 Python基础——文件操作&函数 续


    3.6函数进阶

    名称空间:name space

    例:若变量X=1,1存放于内存中,那存放X与1绑定关系的地方就叫做名称空间。

    名称空间共三种,分别如下:

    • locals:是函数内名称空间,包括局部变量和形参
    • globals:全局变量,函数定义所在模块的名字空间
    • builtins:内置模块的名字空间

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

    作用域即范围:

    • 全局范围:全局存活,全局有效
    • 局部范围:临时存活,局部有效

     注:查看作用域方法 globals(),locals()

    作用域查找顺序:

    level='L0'
    n=22
    
    def func():
          leval='L1'
          n=33
          print(locals())
    
          def outer():
                n=44
                level='L2'
                print(locals(),n)
    
                def inner():#此处打印n是多少?
                      level='L3'    
                      print(locals(),n)
                inner()
            outer()
    
    func()

    问题:在inner()里的打印n的值是多少?

    LEGB代表名字查找顺序:locals->enclosing function->globals->__builtins__

    • locals是函数内的名字空间,包括局部变量和形参
    • enclosing外部嵌套函数的名字区间
    • globals全局变量,函数定义所在模块的名字空间
    • builtins内置模块的名字空间

    闭包

    关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。

    详解:而且,这些内部函数可以访问他们所在外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含他们的外部函数被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必须访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会会受到内部函数的影响。

    def outer():
          name='alex'
    
          def inner():
               print("在inner里打印外层函数的变量“,name)
    
            return inner
    
    f=outer()
    f()

    闭包的意义:返回的函数对象,不仅仅是一个函数对象,在函数外还包裹了一层作用域,这使得该函数无论在何处调用,优先使得自己外层包裹的作用域

    装饰器

    例1:

    #_*_coding:utf-8_*_
    
    user_status = False #用户登录了就把这个改成True
    
    def login():
        _username = "alex" #假装这是DB里存的用户信息
        _password = "abc!23" #假装这是DB里存的用户信息
        global user_status
        if user_status == False:
            username = input("user:")
            password = input("pasword:")
            if username == _username and password == _password:
                print("welcome login....")
                user_status = True
            else:
                print("wrong username or password!")
        else:
            print("用户已登录,验证通过...")
    
    def home():
        print("---首页----")
    
    def america():
        login() #执行前加上验证
        print("----欧美专区----")
    
    def japan():
        print("----日韩专区----")
    
    def henan():
        login() #执行前加上验证
        print("----河南专区----")
    
    home()
    america()
    henan()

    注:在软件开发中有一个原则“开放-封闭”原则,简单来说,它规定已经实现的代码不允许被修改,但可以被扩展,即:

    封闭:已实现的功能代码不应该被修改

    开放:对现有功能的扩展开放

    def login(func): #把要执行的模块从这里传进来
    
        def inner():#再定义一层函数
            _username = "alex" #假装这是DB里存的用户信息
            _password = "abc!23" #假装这是DB里存的用户信息
            global user_status
    
            if user_status == False:
                username = input("user:")
                password = input("pasword:")
    
                if username == _username and password == _password:
                    print("welcome login....")
                    user_status = True
                else:
                    print("wrong username or password!")
    
            if user_status == True:
                func() # 看这里看这里,只要验证通过了,就调用相应功能
    
        return inner #用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数

    简化上边的代码——去掉下边这行

    america=login(america)#你在这里相当于把america这个函数替换了

    最终简化为:

    #_*_coding:utf-8_*_
    
    user_status = False #用户登录了就把这个改成True
    
    def login(func): #把要执行的模块从这里传进来
    
        def inner(*args,**kwargs):#再定义一层函数
            _username = "alex" #假装这是DB里存的用户信息
            _password = "abc!23" #假装这是DB里存的用户信息
            global user_status
    
            if user_status == False:
                username = input("user:")
                password = input("pasword:")
    
                if username == _username and password == _password:
                    print("welcome login....")
                    user_status = True
                else:
                    print("wrong username or password!")
    
            if user_status == True:
                func(*args,**kwargs) # 看这里看这里,只要验证通过了,就调用相应功能
    
        return inner #用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数
    
    
    def home():
        print("---首页----")
    
    @login
    def america():
        #login() #执行前加上验证
        print("----欧美专区----")
    
    def japan():
        print("----日韩专区----")
    
    # @login
    def henan(style):
        '''
        :param style: 喜欢看什么类型的,就传进来
        :return:
        '''
        #login() #执行前加上验证
        print("----河南专区----")
    
    home()
    # america = login(america) #你在这里相当于把america这个函数替换了
    henan = login(henan)
    
    # #那用户调用时依然写
    america()
    
    henan("3p")

    带参数装饰器:

    #_*_coding:utf-8_*_
    user_status = False #用户登录了就把这个改成True
    
    def login(auth_type): #把要执行的模块从这里传进来
        def auth(func):
            def inner(*args,**kwargs):#再定义一层函数
                if auth_type == "qq":
                    _username = "alex" #假装这是DB里存的用户信息
                    _password = "abc!23" #假装这是DB里存的用户信息
                    global user_status
    
                    if user_status == False:
                        username = input("user:")
                        password = input("pasword:")
    
                        if username == _username and password == _password:
                            print("welcome login....")
                            user_status = True
                        else:
                            print("wrong username or password!")
    
                    if user_status == True:
                        return func(*args,**kwargs) # 看这里看这里,只要验证通过了,就调用相应功能
                else:
                    print("only support qq ")
            return inner #用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数
    
        return auth
    
    def home():
        print("---首页----")
    
    @login('qq')
    def america():
        #login() #执行前加上验证
        print("----欧美专区----")
    
    def japan():
        print("----日韩专区----")
    
    @login('weibo')
    def henan(style):
        '''
        :param style: 喜欢看什么类型的,就传进来
        :return:
        '''
        #login() #执行前加上验证
        print("----河南专区----")
    
    home()
    # america = login(america) #你在这里相当于把america这个函数替换了
    #henan = login(henan)
    
    # #那用户调用时依然写
    america()
    
    # henan("3p")

    3.6生成器,迭代器

    列表生成式:

    例:把列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值都加1

    >>> a = [i+1 for i in range(10)]
    >>> a
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10列表生成式]

    这种写法就叫做生成式

    生成式

    在python中一边循环一边计算的机制称为生成器:generator

    要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

    >>> L = [x * x for x in range(10)]
    >>> L
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> g = (x * x for x in range(10))
    >>> g
    <generator object <genexpr> at 0x1022ef630>

    Lg的区别仅在于最外层的[]()L是一个list,而g是一个generator。

    我们可以直接打印出list的每一个元素,想要打印书generator的每一个元素有哦两种方法:

    第一种用next() 

    >>> next(g)
    0
    >>> next(g)
    1
    >>> next(g)
    4
    >>> next(g)
    9
    >>> next(g)
    16
    >>> next(g)
    25
    >>> next(g)
    36
    >>> next(g)
    49
    >>> next(g)
    64
    >>> next(g)
    81
    >>> next(g)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration

    第二种for循环,generator也是可迭送的对象

    >>> g = (x * x for x in range(10))
    >>> for n in g:
    ...     print(n)
    ...
    0
    1
    4
    9
    16
    25
    36
    49
    64
    81

    迭送器

    可以直接作用于for循环的数据类型有以下几种:

    一类是集合数据类型,如listtupledictsetstr等;

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

    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

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

    >>> from collections import Iterable
    >>> isinstance([], Iterable)
    True
    >>> isinstance({}, Iterable)
    True
    >>> isinstance('abc', Iterable)
    True
    >>> isinstance((x for x in range(10)), Iterable)
    True
    >>> isinstance(100, Iterable)
    False

    而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

    *可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

    可以使用isinstance()判断一个对象是否是Iterator对象:

    >>> from collections import Iterator
    >>> isinstance((x for x in range(10)), Iterator)
    True
    >>> isinstance([], Iterator)
    False
    >>> isinstance({}, Iterator)
    False
    >>> isinstance('abc', Iterator)
    False

    生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

    listdictstrIterable变成Iterator可以使用iter()函数:

    >>> isinstance(iter([]), Iterator)
    True
    >>> isinstance(iter('abc'), Iterator)
    True

    Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

    Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

  • 相关阅读:
    C语言时间函数
    sqlplus 配置方法及相关命令
    EDdb 是ED数据
    关于数据库性能管理专家的一个网站
    实用小技巧:在键盘没有小键盘时怎么打开任务管理器
    l来自wentao:项目加入缓存(redis),实时调试时用 -----可视化缓存,flushdb
    转:影响数据检索效率的几个因素
    apache-storm-1.0.3安装部署
    Hadoop2.7.3+spark2.1.0+hbase0.98分布式集群部署
    /etc/security/limits.conf的相关说明
  • 原文地址:https://www.cnblogs.com/cnlogs1/p/9553468.html
Copyright © 2020-2023  润新知