day12-高阶函数和迭代器生成器

1.函数作为变量

1)函数就是变量

python中声明函数其实就是声明一个类型是function的变量,函数名就是变量名;变量能做的函数都能做

a = 10
def func1():
    return '=='
def func2():
    return '====='
print(id(a), id(func1))
print(type(a), type(func1))
# 1.变量可以给别的变量赋值
b = a
c = func1
print(c())
# 2.重新给变量赋值
a = 'abc'
func1 = 100
print(func1*2)
func1 = func2
# 3.变量作为容器类型数据的元素
list1 = [a, 10, func1]
print(list1)
print(list1[-1]())
# 4.变量作为函数的参数
def func3(num):
    sum1 = num ** num
    return sum1
print(func3(3))
a = 4
print(func3(a))
# 函数作为函数的参数  - 实参高阶函数
def func4(fn):
    fn()
def func5(x=10):
    print(x)
func4(func5)

2)系统实参高阶函数:列表.sort\sorted\max\min...中有个参数key,类型就是function。

key的用法:
key是一个函数,必须有且只有一个参数(代表序列中的元素),还有一个返回值(返回值就是比较标准)

students = [
    {'name': 'a', 'age': 22, 'score': 99},
    {'name': 'b', 'age': 20, 'score': 29},
    {'name': 'c', 'age': 24, 'score': 86},
    {'name': 'd', 'age': 17, 'score': 44}
]
def test(x):
    print(x)
    return x['age']
students.sort(key=test)
print(students)
# 练习:将列表nums中所有元素按各位数的和从小到大排序
nums = [19, 29, 54, 81, 75, 23]
def test1(item):
    print(item)
    sum1 = 0
    for x in str(item):
        sum1 += int(x)
    return sum1
nums.sort(key=test1)
print(nums)
# max的原理
def ysy_max(seq, key=None):
    if key:
        list1 = list(seq)
        max1 = list1[0]
        for item in list1[1:]:
            if key(item) > key(max1):
                max1 = item
        return max1
    else:
        list1 = list(seq)
        max1 = list1[0]
        for item in list1[1:]:
            if item > max1:
                max1 = item
        return max1
print(ysy_max([12, 34, 52]))
print(ysy_max('1d2s1'))
print(ysy_max({'name': 'a', 'age': 12}))
print(ysy_max([13, 12, 44], key=lambda item: item % 10))
# 5.变量作为函数的返回值
# 函数作为函数的返回值(返回值高阶函数)
def operation(char):
    if char == '+':
        def sum1(*nums):
            x = 0
            for num in nums:
                x += num
            return x
        return sum1
    elif char == '*':
        def sum2(*nums):
            x = 1
            for num in nums:
                x *= num
            return x
        return sum2
print(operation('+')(12, 90, 22))

2.装饰器

1)什么是装饰器

装饰器的本质就是函数,是用来给函数添加功能用的

装饰器 = 实参高阶函数 + 返回值高阶函数 + 糖语法

# 实例一:给函数添加功能(统计执行时间的功能)
def func1(x, y):
    print(x + y)
func1(10, 20)
def func2():
    print('   *')
    print('====')
func2()
# 实例二:用实参高阶函数给不同的函数添加相同功能
def statistics_time(fn, *args, **wkargs):
    t1 = time.time()
    fn(*args, **wkargs)
    t2 = time.time()
    print('时间:{}s'.format(t2 - t1))
statistics_time(func1, y=1, x=2)
# 实例三:无参装饰器
"""
a.语法
def 函数1(fn):
    def 函数2(*args, **kwargs):
        实现添加功能的代码
        fn(*args, **kwargs)
    return 函数2
b.说明:
函数名1 - 装饰器的名字(根据添加的功能来命名)
fn  - 类型是函数,指向的是需要添加功能的函数
函数名2 - 实现添加功能的函数,名字随便命名,一般为test 
"""
def add_time(fn):
    def test(*args, **kwargs):
        t1 = time.time()
        fn(*args, **kwargs)
        t2 = time.time()
        print(t2-t1)
    return test
@add_time
def func5():
    print('5')
func5()
# 实例四:有参装饰器
"""
有参装饰器的写法:
def 装饰器名(参数列表):
    def 函数名1(fn):
        def test(*args,**kwargs):
            fn(*args,**kwargs)
            添加新功能
        return test
    return 函数1
    
说明:参数列表 - 装饰器添加功能的时候变化的部分通过参数列表来确定
"""
def tag(name):
    def func11(fn):
        def test(*args, **kwargs):
            re_str = fn(*args, **kwargs)
            new_str1 = '<%s>' % name + re_str + '<%s>' % name
            return new_str1
        return test
    return func11
@tag(name='p')
def render(text):
    # 执行其他操作
    return text

练习1:写一些装饰器,实现函数结束调用结束后打印‘调用完成’

def add_print(fn):
    def test(*args, **kwargs):
        fn(*args, **kwargs)
        print('调用完成')
    return test
@add_print
def func6(m):
    print(m**2)
func6(8)

练习2:写一个装饰器,实现将返回值是整数的函数的返回值以十六进制的形式返回

def hex_result(fn):
    def test(*args, **kwargs):
        re = fn(*args, **kwargs)
        return hex(re)
    return test
@hex_result
def func7(m):
    return m ** 2
print(func7(2))

3.迭代器

1)什么是迭代器(iter)

迭代器是容器型数据类型(序列),迭代器中的元素只能通过将其他序列转换成迭代器或者创建生成器
迭代器中的元素:如果需要查看元素,需要将元素从迭代器取出,而且一旦取出就不能再放回去

2)创建迭代器

iter(序列) - 将序列转换成迭代器并返回

iter1 = iter('akq')
print(iter1)

iter2 = iter({'name': 'a', 'age': 19})
print(iter2)

3)获取元素

1)获取单个元素
next(迭代器) / 迭代器.next()

item = next(iter2)
print(item)        # name
item = next(iter2)
print(item)        # age
# item = next(iter2)
# print(item)        # 报错:StopIteration

2)遍历迭代器

print('======')
for x in iter1:
    print('x:', x)
    
# 练习:
iter1 = iter('hello')
list1 = list(iter1)
print(list1)   # ['h', 'e', 'l', 'l', 'o']
# print(next(iter1))   # 报错:StopIteration

4.生成器

1)什么是生成器

生成器就是迭代器,容器有产生数据的能力。

1)怎么创建生成器:调用一个带有yield关键字的函数,就可以得到一个生成器对象

2)生成器产生数据的原理:
当调用一个带有yield关键字函数的时候,不会执行函数体,也不会获取返回值,而是创建一个生成器;
生成器能产生多少个数据,以及每个数据的值,看执行完函数体会遇到几次yield生成器就可以产生几个数据,
yield后面的数据就是会产生的数据
每次获取生成器的元素的时候,都会去执行相应的函数的函数体,执行到yield为止,取下一个元素,
从上次结束的位置接着往后执行

def func1():
    print('=====')
    print('+++++')
    yield [8, 9]
    print('----')
    yield 4
re = func1()
print('re:', re)
print(next(re))
print('第一次结束')
print(next(re))

练习:写一个学号生成器,能够产生的学号的范围和学号的前缀创建生成器的时候自己决定

def creat_id(pre, num):
    length = len(str(num))
    for x in range(num):
        yield pre+str(x).zfill(length)
py_creater = creat_id('python', 200)
print(next(py_creater))

5.生成式

1)什么是生成式

生成式就是生成器的一种简写方式

1)形式一:
(表达式 for 变量 in 序列) - 序列有多少个元素,生成器就能产生多少个数据,每次循环表达式的值就是产生数据的值

相当于:
def func1():
for 变量 in 序列:
yield 表达式

2)形式二:
(表达式 for 变量 in 序列 if 条件语句)

def func1():
for 变量 in 序列:
if 条件语句:
yield 表达式

gen1 = (x*2 for x in range(5))
print(gen1)
print(next(gen1), next(gen1))

gen2 = (x*2 for x in range(5) if x % 2)
print(next(gen2))

2)变形

1)列表生成式
[表达式 for 变量 in 序列] 相当于 list((表达式 for 变量 in 序列))
[表达式 for 变量 in 序列 if 条件语句]

2)集合生成式
{表达式 for 变量 in 序列} 相当于 set((表达式 for 变量 in 序列))
{表达式 for 变量 in 序列 if 条件语句}

3)生成式转字典
dict(表达式 for 变量 in 序列)

list1 = [x*2 for x in range(5)]
print(list1)
list2 = [x*2 for x in range(5) if x % 2]
print(list2)
set2 = {x*2 for x in range(5) if x % 2}
print(set2)

dict1 = dict((x*2, x) for x in range(5) if x % 2)
print(dict1)

练习:用一行代码实现交换一个字典的键对,产生新的字典

dict2 = {'a': 1, 'b': 2, 'c': 3}
new_dict2 = dict((dict2[key], key) for key in dict2)
print(new_dict2)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容