第1章·函数进阶

名称空间

 又叫命名空间,名字空间,英文名叫 name space,干嘛用的?

 假如有 x = 1 , 1是存放到内存的,那 x 存哪里的呢?名称空间正式存放名字x与1绑定关系的地方。

名称空间分3种:

  • locals:是函数内的名称空间,包括局部变量和形参。通过locals()可以打印当前名称空间的局部变量,如果在函数里就是函数里的局部变量。
  • globals:全局变量,函数定义所在模块的名字空间。通过globals()可以打印所有的全局变量,无论是在函数内还是函数外。
  • builtins:内置模块的名字空间。可通过dir(__builtins__)打印所有的内置方法

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

作用域即范围:

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

作用域查找顺序:

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

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

闭包

首先看例子:

def func():
    name = "Alex"

    def inner():
        print("在inner里打印name:", name)

    return inner

f = func()
f()

输出:

在inner里打印name: Alex

以上例子可以看出,嵌套函数中,直接执行func函数,里面的inner函数并没有执行,而是func函数将inner函数对象返回给了外部,给到了f ,这时候 f 实际上就是inner函数,f 加上括号就相当于直接执行inner函数。这样使得嵌套在函数内的子函数在外部也可被调用执行,调用的时候依然能够获取inner函数所在作用域的变量以及参数。

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

闭包的意义:

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

装饰器

 内容太多了,还是直接看大王的故事:

http://www.cnblogs.com/alex3714/articles/5765046.html

装饰器就是在不修改原来程序的情况下给程序添加新的功能。

软件开发中的一个原则:开放-封闭 原则
开放:已实现的功能代码块不应该被修改
封闭:对现有功能的扩展开放

装饰器练习题

'''
一:编写3个函数,每个函数执行的时间是不一样的,
提示:可以使用time.sleep(2),让程序sleep 2s或更多,

二:编写装饰器,为每个函数加上统计运行时间的功能
提示:在函数开始执行时加上start=time.time()就可纪录当前执行的时间戳,函数执行结束后在time.time() - start就可以拿到执行所用时间

三:编写装饰器,为函数加上认证的功能,即要求认证成功后才能执行函数

四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
提示:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式
'''

import time


def runtime(func):
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        run_time = end_time - start_time
        print("run time:", run_time)

    return inner


def get_account_from_file():
    f = open("account2.txt", mode="r", encoding="utf-8")
    data = eval(f.read())
    f.close()
    return data


login_status = False


def login(func):
    def inner(*args, **kwargs):
        global login_status
        if login_status == False:
            username = input("username:>")
            password = input("password:>")
            account_dict = get_account_from_file()
            if username == account_dict["name"] and password == account_dict["password"]:
                print("登录成功")
                login_status = True
            else:
                print("用户名或密码错误.")

        if login_status:
            print("已通过验证..")
            func(*args, **kwargs)

    return inner


@login
@runtime
def func1():
    print("func1 running...")
    time.sleep(2)


@login
@runtime
def func2():
    print("func2 running...")
    time.sleep(3)


@login
@runtime
def func3():
    print("func3 running...")
    time.sleep(1)


func1()
func2()
func3()

 列表生成式

有一个需求是 有一个列表,要对列表里的每个元素加1,如何做,有以下几种:

# 版本一:
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = []
for i in a:
    b.append(i + 1)
print(b)  # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 版本二:
c = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for index, i in enumerate(c):
    c[index] = i + 1
print(c)  # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 版本三:
d = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
d = list(map(lambda x: x + 1, d))
print(d)  # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 版本四:列表生成式
e = [i + 1 for i in range(10)]
print(e)  # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
f = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
f = [i if i < 5 else i * i for i in f]    # 列表生成式
print(f)  # 输出:[0, 1, 2, 3, 4, 25, 36, 49, 64, 81]

 生成器

猜你喜欢

转载自www.cnblogs.com/alexchenx/p/9100615.html
今日推荐