函数—函数进阶(二)

函数—函数进阶(二)

  • 函数—函数进阶—列表生成式

 1 #列表回顾
 2 name = [2,5,7,9,4]
 3 print(name)
 4 for i in name:
 5     print(i)
 6 #结果为:
 7 # [2, 5, 7, 9, 4]
 8 # 2
 9 # 5
10 # 7
11 # 9
12 # 4
13
14 #枚举
15 for index,i in enumerate(name):
16     print(index,i)
17 #结果为:
18 # 0 2
19 # 1 5
20 # 2 7
21 # 3 9
22 # 4 4
23
24
25 #问题:把列表里的每个值加1
26 #二逼青年版
27 a = [0,1,2,3,4,5,6,7,8,9]
28 print(a)               #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
29 b = []
30 for i in a:b.append(i+1)
31 print(b)                 #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
32 a = b             #将b列表赋值给a列表
33 print(a)               #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
34
35 #普通青年版
36 a = [0,1,2,3,4,5,6,7,8,9]
37 print(a)               #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
38 for index,i in enumerate(a):        #通过索引值增加
39     a[index] += 1
40 print(a)               #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
41
42 #文艺青年版
43 a = [0,1,2,3,4,5,6,7,8,9]
44 print(a)               #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
45 a = map(lambda x:x+1,a)
46 print(a)              #结果为:<map object at 0x000001853C723FD0>
47 for i in a:
48    print(i)           #结果为:1,2,3,4,5,6,7,8,9,10
49
50
51 #装逼青年版(列表生成式)
52 a = list(range(10))
53 print(a)               #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
54 a = [i+1 for i in a]        #列表生成式
55 print(a)              #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
56
57 a = [i for i in a]
58 print(a)              #结果为:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
59
60 a = [i*i for i in a]
61 print(a)              #结果为:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
62
63 #三元运算
64 b = list(range(10))
65 print(b)               #结果为:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
66 b = [i if i < 5 else i*i for i in b]
67 print(b)              #结果为:[0, 1, 2, 3, 4, 25, 36, 49, 64, 81]
68
69
70 #既可以循环元组,字典,还可以循环字符串
71 c = ‘alexli‘
72 c = [i for i in c]
73 print(c)             #结果为:[‘a‘, ‘l‘, ‘e‘, ‘x‘, ‘l‘, ‘i‘]
74
75 #字符串可以相加
76 c = ‘alexli‘
77 c = [i+‘w‘ for i in c]
78 print(c)             #结果为:[‘aw‘, ‘lw‘, ‘ew‘, ‘xw‘, ‘lw‘, ‘iw‘]
79
80 #字符串可以相乘
81 c = ‘alexli‘
82 c = [i*2 for i in c]
83 print(c)             #结果为:[‘aa‘, ‘ll‘, ‘ee‘, ‘xx‘, ‘ll‘, ‘ii‘]
  • 函数—函数进阶—生成器

通过列表生成式可以直接创建一个列表。但是受到内存限制,列表容量是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

如果列表元素可以按照某种算法推算出来,可以在循环的过程中不断推算出后续的元素。这样就不必创建完整的list,从而节省大量的空间。

在Python中,这种一边循环一边计算的机制,称为生成器:generator。

 1 #创建一个包含1000个元素的列表
 2 a = [i for i in range(1000)]
 3 print(a)
 4
 5 #生成器(把一个列表生成式的[]改成(),就创建了一个generator )
 6 a2 = (i for i in range(1000))
 7 print(a2)                     #结果为:<generator object <genexpr> at 0x000002B27DF5A048>
 8 print(next(a2))               #结果为:0
 9 print(next(a2))               #结果为:1
10 print(next(a2))               #结果为:2
11 print(next(a2))               #结果为:3
12 print(next(a2))               #结果为:4
13 print(next(a2))               #结果为:5
14 print(next(a2))               #结果为:6
15 print(next(a2))               #结果为:7
16 print(next(a2))               #结果为:8
17 #停止
18 print(a2)                     #结果为:<generator object <genexpr> at 0x0000018F10C2A048>
19 #继续
20 print(next(a2))               #结果为:9
21 print(next(a2))               #结果为:10
22 print(next(a2))               #结果为:11
23 print(next(a2))               #结果为:12
24
25 #小结:
26 #使用next(a2)方法
27 #一个个的打印,可以打印1000个,不占用内存空间。
28 # 这种方法只能够向前,不能够后退。
29 #到最后的时候,会报错
30
31 a = (i for i in range(5))
32 print(next(a))          #结果为:0
33 print(next(a))          #结果为:1
34 print(next(a))          #结果为:2
35 print(next(a))          #结果为:3
36 print(next(a))          #结果为:4
37 print(next(a))          #结果为:StopIteration
  • 函数—函数进阶—斐波那契

1 #这种不断调用next(a)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象
2 #for 循环
3 a = (i for i in range(10))
4 for i in a:
5     print(i)                 #结果为:0  1  2  3  4  5  6  7  8  9
6
7 #while 语句
8 while True:
9     print(next(a))          #结果为:0  1  2  3  4  5  6  7  8  9    但是会报错
 1 #range就是生成器的原理生成的
 2 ‘‘‘
 3 range在Python3与Python2中range的区别:
 4 Python3(生成器):
 5 E:\Python>python3
 6 Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.19
 7 14 64 bit (AMD64)] on win32
 8 Type "help", "copyright", "credits" or "license" for more informa
 9 tion.
10 >>> range(100)
11 range(0, 100)      不会占用内存
12
13 Python2:
14 E:\Python>python2
15 Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.
16 1500 64 bit (AMD64)] on win32
17 Type "help", "copyright", "credits" or "license" for more informa
18 tion.
19 >>> range(10)
20 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
21
22 在Python2中,如何用生成器方式表示range:
23 E:\Python>python2
24 Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit
25 (AMD64)] on win32
26 Type "help", "copyright", "credits" or "license" for more information.
27 >>> xrange(1000000)
28 xrange(1000000)
29
30 总结:Python2中的xrange(100000)等价于Python3中的range(100000)
31 ‘‘‘
 1 #著名的斐波拉契数列(Fibonacci):除第一个和第二个数外,任意一个数都可由前两个数相加得到:
 2 #1, 1, 2, 3, 5, 8, 13, 21, 34, ...
 3 #斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:
 4
 5 a,b = 1,2
 6 print(a)               #结果为:1
 7 print(b)               #结果为:2
 8
 9 #斐波那契数列
10 def fib(max):
11     n, a, b = 0, 0, 1              #n=0 a=0 b=1
12     while n < max:
13         print(b)
14         a, b = b, a+b              #将b的值赋值给a,同时将a+b的值赋值给b
15         n = n + 1
16     return ‘done‘
17 fib(15)                            #结果为:1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
18
19 # 赋值语句:  a, b = b, a + b
20 # 相当于:
21 # t = a + b
22 # a = b
23 # b = t
24
25
26 #生成器(yield)
27 def fib(max):
28     n, a, b = 0, 0, 1
29     while n < max:
30         print(‘before yield‘)
31         yield b                        #yield的作用:把函数的执行过程冻结在这一步并且把b的值返回给外面的next()方法
32         print(b)
33         a, b = b, a+b
34         n = n + 1
35     return ‘done‘
36
37 f = fib(15)                            #将功能转换成一个“生成器”
38 next(f)
39 next(f)
40 next(f)
41 next(f)
42 #结果为:
43 # before yield
44 # 1
45 # before yield
46 # 1
47 # before yield
48 # 2
49 # before yield
50
51 #小结:
52 # yield 把函数的执行过程冻结在了这一步
53 # 此时可以把 b 的值,返回给外面的 next() 方法
54 # 函数名添加(),内部代码不执行,只是生成一个生成器对象
  • 函数—函数进阶—生成器调用方法

 1 #生成器
 2 a = (i for i in range(10))
 3 print(a)                      #结果为:<generator object <genexpr> at 0x0000022D719CA408>
 4 print(next(a))                #结果为:0
 5 print(next(a))                #结果为:1
 6 print(next(a))                #结果为:2
 7 print(next(a))                #结果为:3
 8 print(next(a))                #结果为:4
 9 print(next(a))                #结果为:5
10
11 #while
12 a = (i for i in range(10))
13 while True:
14     print(next(a))
15
16 #for 循环
17 a = (i for i in range(10))
18 for i in a:
19     print(i)
20 ‘‘‘
21 总结:
22 Python2:
23    range = list
24    xrange = 生成器
25
26 Python3:
27    range = 生成器
28    xrange   没有
29 ‘‘‘
  • 函数—函数进阶—函数写生成器

 1 ‘‘‘
 2 生成器的创建方式:
 3   1、列表 生成 式 ()  只能写一个三元运算
 4   2、函数
 5 ‘‘‘
 6 #函数
 7 def range2(n):
 8     count = 0
 9     while count < n:
10         print(count)
11         count += 1
12 range2(10)                        #函数内部执行
13
14
15 #将函数变为生成器
16 def range2(n):
17     count = 0
18     while count < n:
19         print(‘count‘,count)
20         count += 1
21         yield count     #类似return, yield 使程序冻结,next 解冻
22 range2(10)               #因为 yield 没有返回结果
23 print(range2(10))                   #结果为:<generator object range2 at 0x0000024840A7A408>
24 new_range = range2(10)
25 r1 = next(new_range)                #结果为:count 0
26 print(r1)                           #结果为:1
27 print(‘干点别的事...‘)            #结果为:干点别的事...
28 r2 = next(new_range)                #结果为:count 2
29 print(r2)                           #结果为:2
30
31 # 除了使用next()方法外,还可以使用new_range.__next__()
32 new_range.__next__()                #结果为:count 2
33
34 ‘‘‘
35 小结
36 yield vs return
37 return 返回并且中止function
38 yield 返回数据并且冻结当前的执行过程
39 next 唤醒冻结的函数执行过程,继续执行,直到遇到下一个yield
40 ‘‘‘
41 ‘‘‘
42 生成器:
43 之前的函数从调用起,就必须等待执行结果结束,并返回计算值
44 生成器可以把函数整个运行过程中的结果,返回至外面
45 yield,是暂停的意思
46 ‘‘‘
  • 函数—函数进阶—生成器send方法

 1 # def range2(n):
 2 #     count = 0
 3 #     while count < n:
 4 #         print(‘count‘,count)
 5 #         count += 1
 6 #         yield count          #类似于return,yield使程序冻结,next才解冻
 7 #     print(‘-------‘)
 8 #     return 333333
 9 #
10 # new_range = range2(3)
11 #
12 # n1 = next(new_range)
13 # n2 = next(new_range)
14 # n3 = next(new_range)
15 # n4 = next(new_range)
16 # print(n3)
17 # print(n4)
18
19 ‘‘‘
20 函数有了yield之后:
21  1、函数名称加(),就得到了一个生成器
22  2、return 在生成器里代表生成器的终止,直接报错
23 ‘‘‘
24
25 def range2(n):
26     count = 0
27     while count < n:
28         print(‘count‘,count)
29         count += 1
30         sign = yield count               #类似于return,yield使程序冻结,next才解冻
31         if sign == ‘stop‘:
32              print(‘--sign‘,sign)
33              break
34     return 333333              #函数中有了yield 就不会被执行了
35
36 new_range = range2(3)
37 n1 = next(new_range)
38
39 new_range.send(‘stop‘)
40
41 #send方法的作用:
42 #1、唤醒并继续执行,next方法只能唤醒
43 #2、发送一个信息到生成器内部
  • 函数—函数进阶—迭代器

 1 ‘‘‘
 2 我们已经知道,可以直接作用于for循环的数据类型有以下几种:
 3
 4 一类是集合数据类型,如list、tuple、dict、set、str等;
 5
 6 一类是generator,包括生成器和带yield的generator function。
 7
 8 这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
 9 ‘‘‘
10 #可以使用isinstance()判断一个对象是否是Iterable对象
11 from collections import Iterable
12 print(isinstance(‘abc‘,Iterable))           #结果为:True
13 print(isinstance(100,Iterable))              #结果为:False
14 print(isinstance([],Iterable))               #结果为:True
15 print(isinstance({ },Iterable))              #结果为:True
16 print(isinstance((x for x in range(10)),Iterable))      #结果为:True
17
18 #生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
19 #可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
20
21 #可以使用isinstance()判断一个对象是否是Iterator对象:
22 from collections import Iterator
23 print(isinstance((x for x in range(10)), Iterator))             #结果为:True
24 print(isinstance([], Iterator))                           #结果为:False
25 print(isinstance({}, Iterator))                           #结果为:False
26 print(isinstance(‘abc‘, Iterator))                       #结果为:False
27
28 #生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
29
30 #但是可以把list、dict、str等Iterable变成Iterator,使用iter()函数:
31 print(isinstance(iter([]), Iterator))                      #结果为:True
32 print(isinstance(iter(‘abc‘), Iterator))                  #结果为:True
33
34 ‘‘‘
35 那么,为什么list、dict、str等数据类型不是Iterator?
36
37 因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。
38 可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据。
39 所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
40 Iterator甚至可以表示一个无限大的数据流,例如,全体自然数。而使用list是永远不可能存储全体自然数的。
41
42 在当前的阶段,generator与Iterator基本是一致的。
43
44 小结:
45 1、凡是可作用于for循环的对象都是Iterable类型
46 2、凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列
47 3、集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
48 4、Python3的for循环本质上就是通过不断调用next()函数实现的,例如:
49
50 for x in [1, 2, 3, 4, 5]:
51     pass
52 等价于:
53 it = iter([1, 2, 3, 4, 5])
54
55 # 循环
56 while True:
57     try:
58         x = next(it)
59     except StopIteration:
60         break
61 ‘‘‘

原文地址:https://www.cnblogs.com/wqq0723/p/9620604.html

时间: 2024-11-05 10:28:58

函数—函数进阶(二)的相关文章

Lua进阶(二)——函数环境、包

函数环境 function foo() print(g or "No g defined!") end foo() setfenv(foo, { g = 100, print = print }) --设置foo的环境为表{ g=100, ...} foo() print(g or "No g defined!") --No g defined! --100 --No g defined! 定义:函数环境就是函数在执行时所见的全局变量的集合,以一个表来承载. 说明:

函数二----函数的进阶

一.命名空间(有三种) 1.内置的命名空间   -----python解释器 就是python解释器一启动就可以使用的名字存储再内置的命名空间中 内置的名字在启动解释器的时候被加载进内存里. 2.全局命名空间    -----我们写的代码,但不是函数中的代码 是在程序从上到下被执行的过程中依次加载进内存的 放置了我们设置的所有变量名和函数名 3.局部命名空间   -----函数 就是函数内部定义的名字 当调用函数的时候,才会产生这个名称空间,随着函数执行的结束,这个命名空间就又消失了 三种命名空

基础学习之第十天(函数的进阶)

函数的进阶顺序:位置参数->动态接收位置参数*->默认值->动态接收关键字参数**     位置参数->*args->默认参数值->**kwargs一.函数参数--动态传参 1.动态接受位置参数 在参数位置编写*表示接收任意内容 动态接收参数的时候要注意:动态参数必须在位置参数后面 2.动态接收关键字参数 动态接收关键字参数一定在最后面 在实参位置使用*或**,他们是用来打散列表和字符串的二.名称空间,局部名称空间,作用域,加载顺序 在python解释器开始执行之后,

万恶之源-函数的进阶

前?高能-函数的进阶 本节主要内容: 函数参数--动态传参 名称空间,局部名称空间,全局名称空间,作?用域,加载顺序. 函数的嵌套 gloabal, nonlocal关键字 ?一. 函数参数--动态传参 之前我们说过了了传参, 如果我们需要给?一个函数传参, ?而参数?又是不确定的. 或者我给?一个 函数传很多参数, 我的形参就要写很多, 很?麻烦, 怎么办呢. 我们可以考虑使?用动态参数. 形参的第三种: 动态参数 动态参数分成两种: 动态接收位置参数 ?首先我们先回顾?一下位置参数, 位置参

函数用法进阶

目录 函数用法进阶 一.函数作为参数和变量来使用 二.闭包 三.迭代器 函数用法进阶 一.函数作为参数和变量来使用 函数名表示的是函数存储在内存中的地址,函数加上括号才是函数.例如:main()表示的是函数, main是该函数的函数名,print(main)得到的是main()的内存地址,原理等同于直接赋值,可以把函数名赋值给一个变量使用,可以把函数名作为参数来使用,也可以函数名作为返回值来进行传递,等到调用的时候在加上括号,直接就可以调用函数了. def f1(): print('麻花腾')

c语言中二维数组作函数参数以及二维数组的理解

当二维数组作函数参数接受主调函数中的二维数组时,退化为一个指向数组的指针. 在此引用<c与指针>中的观点:作为函数 参数的多位数组名的穿递方式和一维数组名相同--实际传递的是个指向数组第一个元素的指针.但是,两者之间的区别在于, 多维数组的每个元素本身是另外一个数组,编译器需要知道它的维数,以便为函数形参的下标表达式进行求值.

生成器函数的进阶和表达式and各种推导式

生成器函数的进阶 send的效果与作用范围和next一模一样 send获取下一个值的效果和next基本一致 第一次不能用send 函数中的最后一个yield不能接收新的值 只是再获取下一个值的时候,给上一个yield的位置传递一个数据 使用send的注意事项 #第一次使用生成器的时候,是用next获取下一个值 #最后一个yield不能接收外部的值 def generator(): print(123) content = yield 1 print('=======',content) prin

PHP 常用函数总结(二)

4.PHP处理数据库的常用函数. 汇总表 PHP 5 MySQLi 函数 函数 描述 mysqli_affected_rows() 返回前一个 Mysql 操作的受影响行数. mysqli_autocommit() 打开或关闭自动提交数据库修改功能. mysqli_change_user() 更改指定数据库连接的用户. mysqli_character_set_name() 返回数据库连接的默认字符集. mysqli_close() 关闭先前打开的数据库连接. mysqli_commit() 提

lua函数精讲(二)

Lua中的函数带有词法定界的第一类值. 第一类值: 在Lua中,函数和其他值(数值,字符串)一样,函数可以被存放在变量中,也存放在表中, 可以作为函数的参数,还可以作为函数的返回值. 词法定界:被嵌套的函数可以访问他外部函数的变量. lua的函数也可以是匿名的,当我们提到函数名时,实际上是说一个指向函数的变量. 闭包 词法界定加上第一类函数是一个功能强大的概念. function sortbygrade(names, grades) table.sort(names, function(n1,n