python 函数(二)

一 函数的嵌套

def func(*args,**kwargs):
    def func_inner(a,b,c):
        print(a,b,c)
    func_inner(*args,**kwargs)
func(1,2,c=3)

  

 

  针对函数的嵌套,外层函数定义阶段,内层函数调用阶段,*args,**kwargs这样写以后,外层函数调用时,只需要和内层函数定义阶段相匹配就ok了。

 

二 三元表达式

  pass

三名称空间(namespace)与作用域

  名称空间:

    名称空间的分类

    名称空间的加载顺序

    名称空间的生命周期

    名称空间 谁可以使用谁

  作用域

    三种名称空间的作用域

    作用范围

四 闭包

  定义:  

    调用外层函数,返回内层函数的地址,这个内层函数是带着外层函数的环境变量返回的。

def foo():
    name='egon'
    def bar():
        print(name)
    return bar
b=foo()
name='alex'
b()

  输出:

egon            foo就是闭包函数,不管在任何位置调用,都自带对外界作用域的引用。

  

  函数名.__closure__

    如果不是闭包函数,返回None

    如果是闭包函数,返回作为闭包函数调用外层环境的变量地址。以元组的形式返回,每个元素都是一个地址。

 

五 关键字

  locals() :返回当前作用域的局部变量。

Return a dictionary containing the current scope's local variables.

  nonlocal :,对外层的变量有用,但不是全局变量。否则,报错。

a=100
def func1():
    def func2():
        nonlocal a
        print(a)
func1()

  报错信息:

SyntaxError: no binding for nonlocal 'a' found

  global

六 函数的本质

  一等公民

  函数名

  egon语录:函数的作用域关系跟定义位置有关,跟调用位置无关。

money=100
def foo():
    print('money:',money)

def bar():
    money=1000
    foo()
bar()

  输出:  

money: 100                  #foo()函数定义在全局。尽管是在bar函数局部名称空间内被调用,但money的作用域还是要去全局中找。

  

 

  在上述例子的基础上的拓展

money=100
def foo():
    print('money:',money)
money=10
def bar():
    money=1000
    foo()
bar()

  输出:

money: 10                                  #money:10 ,这跟函数的从上到下的加载顺序有关,但引用的money是全局变量还是不变的。

  

  

七 带参数的装饰器

  装饰器的外层右加了一层装饰器。

def wrapper(func):
    def bar(*args):
        print('======')
        res=func(*args)
        return res
    return bar
@wrapper
def plus(x,y):
    return x+y

res=plus(2,2)
print(res)                            #这是最基本的装饰器

  

  带参数的装饰器。想要传参数,将参数写在现成的装饰器的外面,在装饰器的外面在套一层函数。最内层被装饰的函数可以调用到外层的所有参数,可以根据第二层的装饰器的参数,来决定第一层装饰器是否执行。

def auth(tag):
    def wrapper(func):
        def bar(*args):
            if tag:
                print('======')
            res=func(*args)
            return res
        return bar
    return wrapper
@auth(0)
def plus(x,y):
    return x+y

@auth(1)
def multi(x,y):
    return x*y

res=plus(2,2)
print(res)
print('---------------------------------')
res=multi(2,3)
print(res)

  

 

  

  egon讲的另一个例子。调用函数时自动将函数地址保存到一个字典中,key值是传的参数,value值是函数内存地址。

func_dict={}

def auth(key):
    def deco(func):
        func_dict[key]=func
    return deco




@auth('foo')                    #@auth('foo)=@wrapper       foo=wrapper(foo)
def foo():
    print('foo')
@auth('bar')
def bar():
    print('bar')

  讲解时的思路是:   因为要传参,所以是 三层装饰器。先定义了auth(key),放一个参数进去。 deco(func),还是正常放函数。   func_dict[key]=func,走到这一步,要实现的功能已经实现了,没必要在写wrapper函数了。

  思路非常清晰。

  这样实现的效果是 auth传入的参数名随意改,对应的函数实际不会变,达到了隐藏函数的效果。最后直接 func_dict['foo']()就可以运行。

 

八 装饰器的一个应用 @wraps

  Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。写一个decorator的时候,最好在实现之前加上functools的wrap,它能保留原有函数的名称和docstring。

  

from functools import wraps

def wrapper(func):
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner

def foo():
    '''
    foo函数
    :return:
    '''
    x=1
    return x
print(foo.__name__,foo.__doc__)
print('*'*50)
@wrapper
def foo():
    '''
    foo函数
    :return:
    '''
    x=1
    return x
print(foo.__name__,foo.__doc__)
print('*'*50)
def wrapper(func):
    @wraps(func)
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner

@wrapper
def foo():
    '''
    foo函数
    :return:
    '''
    x=1
    return x
print(foo.__name__,foo.__doc__)

  输出:

foo 
    foo函数
    :return:
    
**************************************************
inner None
**************************************************
foo 
    foo函数
    :return:

 

posted @ 2017-08-29 16:00  骑者赶路  阅读(212)  评论(0编辑  收藏  举报