py-函数进阶

名称空间

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

名称空间共3种,分别如下

locals: 是函数内的名称空间,包括局部变量和形参

globals: 全局变量,函数定义所在模块的名字空间

builtins: 内置模块的名字空间

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

作用域即范围

全局范围:全局存活,全局有效

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

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

问题:在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()

有权访问另一个函数作用域内变量的函数都是闭包

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

 

列表生成式

>>> [x for x in range(1,11) ]     
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [x+1 for x in range(1,11) ] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> [i if i<5 else i*i for i in range(1,11)] [1, 2, 3, 4, 25, 36, 49, 64, 81, 100]

生成器

 

>>> def fib(num):
    n,a,b = 0,0,1
    while n<num:
        yield b           #冻结,并返回b的值。可以返回状态
        a,b = b,a+b
        n += 1
    return 'done'
     
>>> fib(10)
<generator object fib at 0x0000023C08453AF0>
>>> a= fib(10)    
>>> a   
<generator object fib at 0x0000023C08453BF8>
>>> next(a)       
1
>>> next(a)      
1
>>> next(a)
2
>>> next(a)
3
>>> next(a)        
5
View Code

 

range也是一个生成器,和py2的xrange相同

py2
range = list
xrange = 生成器


py3
range = 生成器
xrange 没有

 

生成器创建方式

1.列表生成式()
2.函数           yield

函数内部任何一个部位,想要冻结返回就用生成器

函数.__next__()
有 yield 再有 return

 

包子机
import time
def consumer(name):
    print("%s 准备吃包子啦!" %name)
    while True:
        baozi = yield
        print(baozi)
        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))


def producer(name):

    c = consumer('A')
    c2 = consumer('B')
    c.__next__()        #由于yield,c会阻塞住,直到返回值
    c2.__next__()
    print("老子开始准备做包子啦!")
    for i in range(10):
        time.sleep(1)
        print("做了2个包子!")
        c.send(i)       # yield 接受到值,于是开始走下面的print语句
        c2.send(i)
                        # 最后不再给yield 传值,
producer('root')

装饰器

带参数装饰器
#_*_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")
View Code

 

 

。。。未完

posted @ 2018-05-16 08:46  元贞  阅读(130)  评论(0编辑  收藏  举报