04_函数编程_下

目录

1.概述

2.作用域

3.函数的嵌套

4.两个关键字

5.闭包

6.装饰器

6.1 内容回顾

6.2 简单举例

7.迭代器

8.生成器

9.推导式

10.匿名函数

11.内置函数


1.概述

"""
函数的嵌套
变量的作用域
闭包
装饰器
迭代器
生成器
推导式
匿名函数
python的内置函数 sorted,filter,map
"""

2.作用域

作用域:变量的访问权限
a = 10  #全局变量
print(a) # 10


def fun():
    b = 20 #局部变量,局部作用域
    print(a)

fun()  # 10

3.函数的嵌套

"""
函数可以嵌套函数

综上:
     1.函数可以作为返回值进行返回
     2.函数可以作为参数进行互相传递
     函数名实际上就是一个变量名,都表示一个内存地址

"""
def fun1():
    b = 20
    def fun2():  #函数的嵌套,局部变量
        pass
    print(b)
    fun2()

print(fun1()) # 20
              # None

练习题:

def func1():
    print(123)
    def fun2():
        print(456)
        def fun3():
            print(789)
        print(1)
        fun3()
        print(2)
    print(3)
    fun2()
    print(4)


func1()

#结果:
123
3
456
1
789
2
4
# 函数可以作为返回值进行返回
def fun():
    def inner():
        print(123)
    print(inner)
    return inner  #返回的是一个函数,此时我们把一个函数当成一个变量进行返回的

b1 = fun()  # b1是func的内部inner
print(b1)
b1()


# 结果:
<function fun.<locals>.inner at 0x0000018DA3365790>
<function fun.<locals>.inner at 0x0000018DA3365790>
123
# 函数可以作为参数进行互相传递
def an():
    print(123)
an() # 123
bn = an
bn() # 123
# #  代理模式
def func(an):  # 此时an收到的是一个函数
    print(an)  # 执行这个函数 

def target():
    print("我是target")


c = 456
func(target)  # 实参可以是函数


#结果:<function target at 0x00000129A9204790>

4.两个关键字

global a # 把外面的全局变量引入到局部
nonlocal #向外找一层,看看有没有该变量,如果有就引入
a = 10


def func():
    # 此时我就想在函数内部修改全局变量a
    global a # 把外面的全局变量引入到局部
    a  = 20 # 创建一个局部变量,并没有去改变全局变量中的a
    


func()
print(a) # 结果:20
def func():
    a = 10
    def func2():
        nonlocal a  #向外找一层,看看有没有该变量,如果有就引入,如果没有,继续向外一层,直到全局(不包括)
        a = 20
    func2()
    print(a)

func() #结果:20

5.闭包

闭包:本质:内层函数对外层函数的局部变量的使用,此时内层函数被称为闭包函数
    1.可以让一个变量常驻与内存
    2. 可以避免全局变量被更改
def func():
    a = 10
    def inner():
        nonlocal a
        a = a + 1
        return a
    return inner

ret = func()

a = 20
r1 = ret()
print(r1) # 11

r2 = ret()
print(r2)# 12

6.装饰器

"""
内容回顾:
      1.函数可以作为参数进行传递
      2.函数可以作为返回值进行返回
      3.函数名称可以当成变量一样进行复制操作


装饰器: -> 要求记住最后的结论
        装饰器就是一个特殊的闭包
        作用:
        再不改变原有函数调用的情况下,给函数增加新的功能
        直白:可以在函数前后添加新功能,但是不改变原来的代码。


        锥形:
        def wrapper(fn):
             def inner(*args,**kwargs):
             函数执行之前。。。。
               ret = fn(*args,**kwargs)
             函数执行之后。。。。
               return ret
             return inner
        @wrapper
        def target():
           pass

        target() # => inner()


    一个函数可以被多个装饰器装饰




"""

6.1 内容回顾

1.函数可以作为参数进行传递
def func():
    print("我是函数")


def ggg(fn):
    fn()



ggg(func) #结果:我是函数
def func():
    def inner():
        print('123')
    return inner

ret = func()
ret()  #结果:123

6.2 简单举例

1.无传参

def guanjia(game):
    def inner():
        print("开启外挂")
        game()
        print("关闭外挂")
    return inner


@guanjia
def play_lol():
    print("德玛西亚")

play_lol()

#结果:
开启外挂
德玛西亚
关闭外挂

2.有传参

def guanjia(game):
    def inner(username,password):
        print("开启外挂")
        game(username,password)
        print("关闭外挂")
    return inner


@guanjia
def play_lol(username,password):
    print("我要开始玩lol了",username,password)
    print("德玛西亚")

play_lol("hcb2001","123")

结果:
开启外挂
我要开始玩lol了 hcb2001 123
德玛西亚
关闭外挂

3.*args,**kwargs

def guanjia(game):
    #     * ** 表示接收所有参数,打包成元组和字典
    def inner(*args,**kwargs):  # arge肯定是一个元组  , kwargs肯定是一个列表
        print("开启外挂")
    #     *,** 表示把args元组和kwargs字典打散 位置参数以及关键字参数传递进去
        game(*args,**kwargs)
        print("关闭外挂")
    return inner
#
#
@guanjia
def play_lol(username,password):
    print("我要开始玩lol了",username,password)
    print("德玛西亚")
#
#
@guanjia
def play_dnf(username,password,hero):
    print("我要开始玩dnf了",username,password,hero)
    print("德玛西亚")

play_lol("hcb2001","123")
play_dnf("hcb2001","123456","墨白")


#结果:
开启外挂
我要开始玩lol了 hcb2001 123
德玛西亚
关闭外挂
开启外挂
我要开始玩dnf了 hcb2001 123456 墨白
德玛西亚
关闭外挂

4.返回值

def guanjia(game):
    #     * ** 表示接收所有参数,打包成元组和字典
    def inner(*args,**kwargs):  # arge肯定是一个元组  , kwargs肯定是一个列表
        print("开启外挂")
    #     *,** 表示把args元组和kwargs字典打散 位置参数以及关键字参数传递进去
        ret = game(*args,**kwargs)
        print("关闭外挂")
        return ret
    return inner

@guanjia
def play_lol(username,password):
    print("我要开始玩lol了",username,password)
    print("德玛西亚")
    return "一把刀"
res = play_lol("hcb2001","123")
print(res)

#结果:
开启外挂
我要开始玩lol了 hcb2001 123
德玛西亚
关闭外挂
一把刀
5.一个函数被多个装饰器装饰
def wrapper1(fn): #fn:wrapper2.inner
    def inner(*args,**kwargs):
        print("这里是wrapper1 进入")
        ret = fn(*args,**kwargs)
        print("这里是wrapper1 出去")
        return ret
    return inner

def wrapper2(fn): #fn:target
    def inner(*args,**kwargs):
        print("这里是wrapper2 进入")
        ret = fn(*args,**kwargs)
        print("这里是wrapper2 出去")
        return ret
    return inner



@wrapper1     # target = wrapper1(wrapper2.inner) => target:wrapper1.inner
@wrapper2    # target = wrapper2(target) => target:wrapper2.inner
def target():
    print("我是目标")

target()


# 结果:
这里是wrapper1 进入
这里是wrapper2 进入
我是目标
这里是wrapper2 出去
这里是wrapper1 出去

7.迭代器

"""
for 变量 in 可迭代:
    pass

iterable: 可迭代的东西
iterator: 迭代器
str, list, tuple, dict, set, open()

可迭代的数据类型都会提供一个叫迭代器的东西. 这个迭代器可以帮我们把数据类型中的所有数据逐一的拿到

获取迭代器的两种方案:
    1. iter() 内置函数可以直接拿到迭代器
    2. __iter__()   特殊方法

从迭代器中拿到数据:
    1. next() 内置函数
    2. __next__() 特殊方法

for里面一定是要拿迭代器的. 所以所有不可迭代的东西不能用for循环
for循环里面一定有__next__出现

总结: 迭代器统一了不同数据类型的遍历工作

迭代器本身也是可迭代的
迭代器本身的特性:
    1. 只能向前不能反复
    2. 特别节省内存
    3. 惰性机制

"""

 1.iter()

it = iter("你叫什么名字啊")

print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))

print(next(it))  # StopIteration: 迭代已经停止了. 不可以再次从迭代器中拿数据了

结果:

it = "呵呵哒".__iter__()

print(it.__next__())
print(it.__next__())
print(next(it))

# 结果:
呵
呵
哒

s = "你好啊, 我叫赛利亚"
it = s.__iter__()

for mm in it:
    print(mm)

#结果:

你
好
啊
,
 
我
叫
赛
利
亚

Process finished with exit code 0

8.生成器

"""
生成器(generator):
    生成器的本质就是迭代器

    创建生成器的两种方案:
        1. 生成器函数
        2. 生成器表达式

    生成器函数
        生成器函数中有一个关键字yield
        生成器函数执行的时候, 并不会执行函数, 得到的是生成器.

        yield: 只要函数中出现了yield. 它就是一个生成器函数
            作用:
                1. 可以返回数据
                2. 可以分段的执行函数中的内容, 通过__next__()可以执行到下一个yield位置
        优势:
            用好了, 特别的节省内存


    生成器表达式 -> 一次性的
        语法: (数据 for循环 if)

"""
生成器函数
def func():
    print(123456)
    yield 999  # yield也有返回的意思.

ret = func()
# print(ret)  # <generator object func at 0x115f2dbd0>
print(ret.__next__())  # yield只有执行到next的时候才会返回数据
print(ret.__next__())  # StopIteration

结果:

def func():
    print(123)
    yield 666
    print(456)
    yield 999

ret = func()
print(ret.__next__())
print(ret.__next__())

#结果:

123
666
456
999

def order():
    lst = []
    for i in range(10000):
        lst.append(f"衣服{i}")
        if len(lst) == 50:
            yield lst
            # 下一次拿数据
            lst = []


gen = order()
print(gen.__next__())
print(gen.__next__())

结果:

9.推导式

"""
推导式:
    简化代码.
    语法:
        列表推导式: [数据 for循环 if判断]
        集合推导式: {数据 for循环 if判断}
        字典推导式: {k:v for循环 if判断}

    不要把推导式妖魔化.
    (数据 for循环 if判断)  -> 不是元组推导式, 根本就没有元组推导式.  这玩意叫生成器表达式

"""
lst = []
for i in range(10):
    lst.append(i)

print(lst) #结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

lst = [i for i in range(10)]
print(lst)  #结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


1. 请创建一个列表[1,3,5,7,9]

lst = [i for i in range(1, 10, 2)]
lst = [i for i in range(10) if i % 2 == 1]
print(lst)

# 结果:[1, 3, 5, 7, 9]
2. 生成50件衣服
lst = [f"衣服{i}" for i in range(50)]
print(lst)

#结果:['衣服0', '衣服1', '衣服2', '衣服3', '衣服4', '衣服5', '衣服6', '衣服7', '衣服8', '衣服9', '衣服10', 。。。。。]
3. 将如下列表中所有的英文字母修改成大写
lst1 = ["allen", "tony", "kevin", "sylar"]
lst2 = [item.upper() for item in lst1]
print(lst2)

#结果:['ALLEN', 'TONY', 'KEVIN', 'SYLAR']
4. 请将下列的列表修改成字典, 要求 索引做为key, 数据作为value
lst = ['赵本山', "潘长江", "高达", "奥特曼"]

dic = {i: lst[i] for i in range(len(lst))}
print(dic)  #结果:{0: '赵本山', 1: '潘长江', 2: '高达', 3: '奥特曼'}

10.匿名函数

"""
匿名函数:
    lambda表达式
    语法:
        变量 = lambda 参数,参数2,参数3....: 返回值

"""
fn = lambda a, b: a + b
ret = fn(12, 13)
print(ret)

# 结果:25

11.内置函数

"""
zip: 可以把多个可迭代内容进行合并
sorted: 排序
filter: 筛选
map:    映射
"""

zip: 可以把多个可迭代内容进行合并

普通:

lst1 = ["赵本山", "范伟", '苏有朋']
lst2 = [40, 38, 42]
lst3 = ["卖拐", "耳朵大有福", "情深深雨蒙蒙"]

result = []
for i in range(len(lst1)):
    first = lst1[i]
    second = lst2[i]
    third = lst3[i]
    result.append((first, second, third))
print(result)

用zip:

lst1 = ["赵本山", "范伟", '苏有朋']
lst2 = [40, 38, 42]
lst3 = ["卖拐", "耳朵大有福", "情深深雨蒙蒙"]

result = zip(lst1, lst2, lst3)
for item in result:
    print(item)


# 结果:
('赵本山', 40, '卖拐')
('范伟', 38, '耳朵大有福')
('苏有朋', 42, '情深深雨蒙蒙')
sorted: 排序
lst = [16,22,68,1,147,256,49]
s = sorted(lst, reverse=True)  # reverse翻转
print(s)

#结果:[256, 147, 68, 49, 22, 16, 1]
# #       1      3        2       4           123132
lst = ["秋", "张二嘎", "比克", "卡卡罗特", "超级宇宙无敌大帅B"]

# def func(item):  # item对应的就是列表中的每一项数据
#     return len(item)

s = sorted(lst, key=lambda x: len(x))
print(s)

#结果:['秋', '比克', '张二嘎', '卡卡罗特', '超级宇宙无敌大帅B']

练习:

lst = [
    {"id": 1, "name": "周润发", "age": 18, "salary": 5200},
    {"id": 2, "name": "周星驰", "age": 28, "salary": 511100},
    {"id": 3, "name": "周海媚", "age": 78, "salary": 561230},
    {"id": 4, "name": "周伯通", "age": 12, "salary": 532100},
    {"id": 5, "name": "周大兴", "age": 35, "salary": 53210},
    {"id": 6, "name": "周周有辣", "age": 47, "salary": 520},
    {"id": 7, "name": "周扒皮", "age": 8, "salary": 12},
]
# 1.根据每个人的年龄排序
s = sorted(lst, key=lambda d: d['age'])
print(s)
#
# # 2.根据工资进行排序. 从大到小
s = sorted(lst, key=lambda d: d['salary'], reverse=True)
print(s)

 结果:

filter: 筛选

lst = ["张无忌", "张三丰", "张翠山", "灭绝小师太", "小狐仙"]
f = filter(lambda x: x.startswith("张"), lst)
print(list(f))

#结果:['张无忌', '张三丰', '张翠山']
map:    映射
lst = [1,2,3,4,5,6,7,8,9]

result = [item * item for item in lst]
print(result)

# 结果:[1, 4, 9, 16, 25, 36, 49, 64, 81]


r = map(lambda x: x * x, lst)
print(list(r))

#结果:[1, 4, 9, 16, 25, 36, 49, 64, 81]

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

激进的猴哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值