函数的定义

def 函数名(参数):
    
    函数体
    
    return   返回值

#def:     定义函数的关键字
#函数名: 函数的名字,用于函数的调用
#参数:    为函数体提供数据
#函数体: 函数里的一系列运算
#返回值: 函数执行完毕后,返回的值

 

 

函数传递参数

按照形参来划分 (位置参数》动态参数》默认参数)

位置形参

def func(a, b, c):   #必须与形参按照顺序一一对应
    print(a, b, c)
func(1, 2, 'oldboy')

默认参数

def func(a, b, c=3, d=4):   #默认参数必须在位置参数的后边
    print(a, b, c, d)
func(1, 2)

 

动态参数

def func(*args, **kwargs):   #函数定义的时候*代表聚合
    print(args)  # args接受所有的位置参数,放在一个元组中
    print(kwargs)  # kwargs接受所有的关键字参数,放在一个字典中
func(1, 2, 3, name='lidawei', age=18)

func(*[1,2,3],*(22,333)) 函数执行的时候*代表打散

 

 

按照实参来划分

位置参数

def func(a, b, c):   #必须与形参按照顺序一一对应
    print(a, b, c)
func(1, 2, 'oldboy')

 

关键字参数

def func(a, b ):   #必须与形参一一对应,顺序可以变,但是个数不能变
    print(a, b)
func(b=1,a=2)

 

混合参数(包括位置参数与关键字参数)

def func(a, b, c, d):   #关键字参数必须在位置参数的后边
    print(a, b, c, d)
func(1, 2, d=4, c=3)

 

函数的名称空间和作用域

名称空间:

当程序运行时代码从上至下一次执行,他会将变量与值的关系存储到一个空间中,这个空间叫做名称空间也叫命名空间

 

python中的名称空间分三种

内置名称空间:python自带的名称空间,在python解释器启动是产生,存放了python内置的变量名与值的绑定关系

全局名称空间:在执行python程序时,存放变量与值关系的空间

局部名称空间:当程序遇到函数时,会将函数名存到内存中,函数体不关心,当函数执行时,内存会开辟一个空间,存放函数的代码,变量等,函数外面访问不到临时空间的内容,随着函数执行完毕,临时空间                         会被释放掉,像这个临时开辟出来的空间叫做临时名称空间,也叫局部名称空间

 

作用域:

    全局作用域:

        内置名称空间

        全局名称空间

    局部作用于:

        局部名称空间

加载顺序 :内置名称空间 ---> 全局名称空间(程序执行时) ---> 局部名称空间(函数执行时)

取值顺序:局部名称空间(函数调用时) --->全局名称空间(程序执行时) --->内置名称空间

 

函数的嵌套:

    嵌套调用:

def max(x,y):
    return x if x > y else y

def max4(a,b,c,d):
    res1=max(a,b)
    res2=max(res1,c)
    res3=max(res2,d)
    return res3
print(max4(1,2,3,4))

 

    嵌套定义:

def f1():
    def f2():
        def f3():
            print('from f3')
        f3()
    f2()

f1()

 

 

内置函数globals() 和 locals()

globals()返回一个字典,字典里边的内容是全局作用域的内容

locals()返回一个字典,字典里边是当前位置的所有变量

 

关键字 global()和 nonlocal()

global(使函数可以引用并改变一个全局变量,在局部作用域声明一个全局变量)

count = 1
def func1():
    global count
    count = count + 1
    print(count)
func1()
print(count)

nonlocal(不能操作全局变量,从哪层开始引用的,就从哪层开始改变)

def func1():
    count = 1
    def inner():
        nonlocal count
        count = count + 3
        print(count)
        def inner2():
           pass
    inner()
    print(count)
func1()

 

取值:引用而不是改变,取值是从小到大取值(LEGB),想改变上层空间的变量,就要用到global nonlocal

 

如果默认参数是一个可变的数据类型,那么他在内存中永远只是一个

def extendList(val,list=[]):
    list.append(val)
    return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print('list1=%s'%list1)  # [10,]
print('list2=%s'%list2)  # [123,]
print('list3=%s'%list3)  #[10,'a']

 

 

函数名的应用:

函数是第一类对象,可以当做数据传递

①可以被引用

②可以作为函数的参数

③可以作为函数的返回值

④可以作为函数的容器类数据的元素

 

闭包:内层函数对外层函数非全局变量的引用

def wrapper():
    name = 'alex'
    def inner():
        print(name)
    inner()
wrapper()

 

#如果python解释器遇到了闭包函数,他有一个机制,这个闭包不会随着函数的结束而释放

 

装饰器

在不修改被装饰对象源代码和被装饰对象的调用方式的前提下,为被装饰对象添加新的功能

 

目的:查看一个函数的运行效率

①引用time模块,得到函数结束时间和开始时间计算得出运行时间

def func1():
    time.sleep(0.3)
    print('正在登陆')

start_time = time.time()
func1()
end_time = time.time()
print('此函数的执行效率%s' %(end_time-start_time))

 

②把上述计算封装在一个函数中

def timer():
    start_time = time.time()
    time.sleep(0.3)
    print('正在登陆')
    end_time = time.time()
    print('此函数的执行效率%s' %(end_time-start_time))
timer()

 

③被测试函数当做参数传入,可以测试多个函数的执行效率

import  time
def func1():
    time.sleep(0.3)
    print('正在登陆')
def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数的执行效率%s' %(end_time-start_time))
timmer(func1)

 

 

④测试函数执行效率的同时,不改变原函数的调用方式

import time
def func1():
    time.sleep(0.3)
    print('非常复杂......')
def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函数的执行效率%s' % (end_time - start_time))
f1 = func1
func1 = timmer  
func1(f1)  # timmer(func1)

 

⑤最简单的装饰器

import time
def func1():
    time.sleep(0.3)
    print('非常复杂......')
def timmer(f):  # f = func1 函数名
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print('此函数的执行效率%s' % (end_time - start_time))
    return inner
func1 = timmer(func1)  # inner
func1()  # inner()

 

⑥带语法糖@的简单装饰器

import time
def timmer(f):  # f = func1 函数名
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print('此函数的执行效率%s' % (end_time - start_time))
    return inner

@timmer  # func1 = timmer(func1)  inner
def func1():
    time.sleep(0.3)
    print('非常复杂......')
func1()  # inner()

 

⑦被装饰的函数带有参数的装饰器

import time
def timmer(f):  # f = func1 函数名
    def inner(*args,**kwargs):
        start_time = time.time()
        f(*args,**kwargs)
        end_time = time.time()
        print('此函数的执行效率%s' % (end_time - start_time))
    return inner

@timmer  # func1 = timmer(func1)  inner
def func1(a,b):
    time.sleep(0.3)
    print(a,b)
    print('非常复杂......')
func1(1,2)

 

⑧被装饰的函数带参数且有返回值的装饰器

import time
def timmer(f):  # f = func2 函数名
    def inner(*args,**kwargs):  # args = (1,2),kwargs {sex:'nv',name:'alex'}
        start_time = time.time()
        ret = f(*args,**kwargs)  # f(1,2,,sex='nv',name='alex')
        end_time = time.time()
        print('此函数的执行效率%s' % (end_time - start_time))
        return ret
    return inner
@timmer  # func2 = timmer(func2)  inner
def func2(a,b,name,sex='man'):  # f(1,2,,sex='nv',name='alex')
    time.sleep(0.3)
    print('非常复杂......')
    return 666

func2(1,2,sex='nv',name='alex') # inner()

 

装饰器的本质就是闭包