Python 学习笔记 - 函数

闭包

在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。

实例

def func():
    name="张书源"
    def inner():
        print("My name is :",name)
    return inner
f=func()
f()

如何判断是否是闭包函数

函数名.__closure__ 在函数是闭包函数时,返回一个cell元素;不是闭包时,返回None。

def func():
    name = '张书源'
    def inner():
        print("My name if :",name)
    print(inner.__closure__)  # (<cell at 0x0000027C14EB85E8: str object at 0x0000027C14F54960>,)
    return inner

f = func()
f()
name = '张书源'
def func():
    def inner():
        print("My name is :",name)
    print(inner.__closure__)  # None
    return inner

f = func()
f()

装饰器

装饰器是给现有的模块增添新的小功能,可以对原函数进行功能扩展,而且还不需要修改原函数的内容,也不需要修改原函数的调用。

装饰器的使用符合了面向对象编程的开放封闭原则。

简单的装饰器

def Time_sleep():
    print("Time sleep 函数启动")
    time.sleep(2)


def count_time(func):       #函数运行时间计时器
    def wrapper():
        ti = time.time()
        func()
        print("执行时间为:", time.time() - ti)

    return wrapper


if __name__ == '__main__':
    Time_sleep = count_time(Time_sleep) 
    Time_sleep()

这里的count_time是一个装饰器,装饰器函数里面定义一个wrapper函数,把func这个函数当作参数传入,函数实现的功能是把func包裹起来,并且返回wrapper函数。wrapper函数体就是要实现装饰器的内容。

装饰器的语法糖@

import time

import time


def count_time(func):
    def wrapper():
        t1 = time.time()
        func()
        print("执行时间为:", time.time() - t1)

    return wrapper


@count_time
def Time_sleep():
    print("Time sleep 函数启动")
    time.sleep(2)


if __name__ == '__main__':
    Time_sleep()  # 用语法糖之后,就可以直接调用该函数了

装饰器传参

当被装饰的函数是带参数时,例如

def blog(name):
    print('进入blog函数')
    name()
    print('我的博客是 https://blog.csdn.net/qq_52902529')

装饰器函数修改成为可以接受任意参数的装饰器,参数为*args和**kwargs,表示可以接受任意参数

def count_time(func):
    def wrapper(*args, **kwargs):
        t1 = time.time()
        func(*args, **kwargs)
        print("执行时间为:", time.time() - t1)

    return wrapper

带参数的装饰器

基于原来的count_time函数外部再包一层用于接收参数的count_time_args,接收回来的参数就可以直接在内部的函数里面调用了

import time


def count_time_args(msg=None):
    def count_time(func):
        def wrapper(*args, **kwargs):
            t1 = time.time()
            func(*args, **kwargs)
            print(f"[{msg}]执行时间为:", time.time() - t1)

        return wrapper

    return count_time


@count_time_args(msg="张书源")
def fun_one():
    time.sleep(1)


@count_time_args(msg="张硕")
def fun_two():
    time.sleep(1)


@count_time_args(msg="汤康丽")
def fun_three():
    time.sleep(1)


if __name__ == '__main__':
    fun_one()
    fun_two()
    fun_three()

lambda表达式

  • lambda只是一个表达式,函数体比def简单很多。
  • lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
  • lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
  • 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

 语法只包含一个语句,如下:

lambda [arg1 [,arg2,.....argn]]:expression

实例: 

sum=lambda a,b:a+b
print("1 + 2 = ", sum(1 , 2))

生成器(gengerator)

生成器是python中的一个对象(按照某种规律,来生成元素的对象),生成器不是列表,保存了产生元素的算法,同时会记录游标的位置(现在拿到第几个元素了),为了下次继续拿数据,而不是从头开始拿数据。可以通过一直调用next()方法获取值,这个对象不保存数据,每次调用会返回一个值,即做到了列表的好处,又不占用空间。

通过类似于列表生成式来创建(将列表换为元组)

list2=(x for x in range(1,11))
print(list2)                 #<generator object <genexpr> at 0x0000020B66A4BF20>
print(type(list2))           #<class 'generator'>

通过函数创建生成器(yield)

def counter():
    i=0
    while i<=5:
        yield i #yield:是没有返回值的,如果赋值的话会打印None
        i+=1

gener=counter()
print(gener) #<generator object counter at 0x00000295F518BF20>
for x in gener:
    print(x)  # 0 1 2 3 4 5

遍历生成器中的元素

next(生成器对象)

每调用一次next(),就会拿掉一个值(表达式中的第一个值),当已经遍历到生成器的结尾,会抛一个异常StopIteration。

def counter():
    i=0
    while i<=5:
        yield i 
        i+=1

gener=counter()
print(next(gener))# 0
print(next(gener))# 1
print(next(gener))# 2
print(next(gener))# 3
print(next(gener))# 4
print(next(gener))# 5
print(next(gener))# 报错
for循环遍历
for x in gener:
    print(x) #不会抛出异常
生成器对象.next()

object内置的__next__,当已经遍历到生成器的结尾,会抛一个异常StopIteration

print(gener.__next__())
list(g)方法
print(list(gener))

生成器内置方法

close() --关闭生成器
send()

和next一样可以用来生成数据,可以往生成器内部传递数据(可以和生成器内部进行交互)

def generator_function():
    value1 = yield 1
    value1 = yield 0
    print("value1的值是 : ",value1)
    value2 = yield 1
    print("value2的值是 : ",value2)
    value3 = yield 2
    print("value3的值是 : ",value3)

g=generator_function()
print(g.__next__()) 
print(g.send(1))    
g.send(1)           
print(g.send(2))   

在上面的代码中,我们先调用 next() 方法,使函数开始执行,代码执行到 yield 1 的时候暂停,返回了 1;接着,我们执行了 send() 方法,它会恢复生成器的运行,并将发送的值赋给上次中断时 yield 表达式的执行结果,也就是 value1,这时我们又执行了send()方法控制台打印出 value1 的值,并继续执行,直到遇到 yield 后暂停,此时返回 2;类似地,再次执行 send() 方法,将值赋给value2。
简单地说, send() 方法就是 next() 的功能,加上传值给 yield 。

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值