python生成器/内置函数

1.摘要
  • 内置函数
  • 生成器/迭代器
  • 常用模块

2.内置函数

  1 abs() --取绝对值
  2 
  3 all() --任意一个元素为0,空,或者false,则返回False,否则返回为True,特别的[],(),{}返回为True
  4 
  5 any() --任意一个元素不为0,空,或者false,则返回True,否则返回为False
  6 
  7 ascii() --转换为ascii对应的字符
  8 
  9 bin() --二进制
 10 hex() --16进制
 11 oct() --8进制
 12 
 13 bool()
 14 
 15 bytearray()    --bytes和字符串不能被修改,byetarray 直接在原内存地址修改
 16 memoryview()  --允许直接修改原内存,参数为bytes格式
 17  
 18 
 19 bytes()
 20 
 21 callable() --是否为可调用的,如函数
 22 
 23 chr() --数字转换成对应ascii字符
 24 
 25 ord() --与chr相反
 26 
 27 eval --字符串形式的表达式解析并执行
 28 
 29 exec() ----字符串形式的代码解析并执行
 30 
 31 compile() --把一个代码文件加载进来,按exec或eval大方式解析并执行
 32 
 33 dir() --查看对象的方法
 34 两个__--私有方法
 35 
 36  divmod() 返回余数和商
 37 
 38 filter()  --返回函数结果为True的列表值
 39 a = range(0,10)
 40 b = filter(lambda x:x>5,a)  --返回结果为true的a中的值
 41 
 42 for i in b:
 43      print(i)
 44 
 45 format()
 46 frozenset() --让集合可修改
 47 globals()  --当前的程序所有的全局变量以字典的形式展示
 48 locals()  --当前的函数所有的全局变量以字典的形式展示
 49 
 50 hash()  --只能保证在当前程序是唯一的,退出后重新执行,不同
 51 
 52 
 53 isinstance()  --判断一个对象是不是实例
 54 
 55 
 56 map()  --
 57 from functools import reduce
 58 a = reduce(lambda x,y:x+y ,range(10))
 59 print(a) --45
 60 
 61 
 62 
 63 import time
 64 for i in range(20):
 65     time.sleep(0.5)
 66     print("#",end='',flush=True)
 67 
 68 print(...)
 69     print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
 70     Prints the values to a stream, or to sys.stdout by default.
 71     Optional keyword arguments:
 72     file:  a file-like object (stream); defaults to the current sys.stdout.
 73     sep:   string inserted between values, default a space.
 74     end:   string appended after the last value, default a newline.
 75     flush: whether to forcibly flush the stream.
 76 
 77 
 78 repr() --
 79 
 80 
 81 reversed()  --反转
 82 round(5.23353,2)  --保留2位小数
 83 
 84 a = list()
 85 compile
 86 f = open("函数递归.py")
 87 data =compile(f.read(),'','exec')
 88 exec(data)
 89 
 90 
 91 print
 92 msg = "又回到最初的起点"
 93 f = open("tofile","w")
 94 print(msg,"记忆中你青涩的脸",sep="|",end="",file=f)
 95 #slice
 96 a = range(20)
 97 pattern = slice(3,8,2)
 98 for i in a[pattern]: #等于a[3:8:2]
 99     print(i)
100 
101 
102 
103 
104 memoryview
105 usage:
106 >>> memoryview(b'abcd')
107 <memory at 0x104069648>
108 在进行切片并赋值数据时,不需要重新copy原列表数据,可以直接映射原数据内存,
109 
110 
111 import time
112 for n in (100000, 200000, 300000, 400000):
113     data = b'x'*n
114     start = time.time()
115     b = data
116     while b:
117         b = b[1:]
118     print('bytes', n, time.time()-start)
119 
120 for n in (100000, 200000, 300000, 400000):
121     data = b'x'*n
122     start = time.time()
123     b = memoryview(data)
124     while b:
125         b = b[1:]
126     print('memoryview', n, time.time()-start)
127 
128 几个内置方法用法提醒
129 
130 zip()
131 按照位置一一合并
132 
133 
134 __import__()  --用户输入的为字符串,导入用户输入的模块

 

 

abs() --取绝对值

all() --任意一个元素为0,空,或者false,则返回False,否则返回为True,特别的[],(),{}返回为True

any() --任意一个元素不为0,空,或者false,则返回True,否则返回为False

ascii() --转换为ascii对应的字符

bin() --二进制
hex() --16进制
oct() --8进制

bool()

bytearray()    --bytes和字符串不能被修改,byetarray 直接在原内存地址修改
memoryview()  --允许直接修改原内存,参数为bytes格式
 

bytes()

callable() --是否为可调用的,如函数

chr() --数字转换成对应ascii字符

ord() --与chr相反

eval --字符串形式的表达式解析并执行

exec() ----字符串形式的代码解析并执行

compile() --把一个代码文件加载进来,按exec或eval大方式解析并执行

dir() --查看对象的方法
两个__--私有方法

 divmod() 返回余数和商

filter()  --返回函数结果为True的列表值
a = range(0,10)
b = filter(lambda x:x>5,a)  --返回结果为true的a中的值

for i in b:
     print(i)

format()
frozenset() --让集合可修改
globals()  --当前的程序所有的全局变量以字典的形式展示
locals()  --当前的函数所有的全局变量以字典的形式展示

hash()  --只能保证在当前程序是唯一的,退出后重新执行,不同


isinstance()  --判断一个对象是不是实例


map()  --
from functools import reduce
a = reduce(lambda x,y:x+y ,range(10))
print(a) --45



import time
for i in range(20):
    time.sleep(0.5)
    print("#",end='',flush=True)

print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.


repr() --


reversed()  --反转
round(5.23353,2)  --保留2位小数

a = list()
compile
f = open("函数递归.py")
data =compile(f.read(),'','exec')
exec(data)


print
msg = "又回到最初的起点"
f = open("tofile","w")
print(msg,"记忆中你青涩的脸",sep="|",end="",file=f)
#slice
a = range(20)
pattern = slice(3,8,2)
for i in a[pattern]: #等于a[3:8:2]
    print(i)




memoryview
usage:
>>> memoryview(b'abcd')
<memory at 0x104069648>
在进行切片并赋值数据时,不需要重新copy原列表数据,可以直接映射原数据内存,


import time
for n in (100000, 200000, 300000, 400000):
    data = b'x'*n
    start = time.time()
    b = data
    while b:
        b = b[1:]
    print('bytes', n, time.time()-start)

for n in (100000, 200000, 300000, 400000):
    data = b'x'*n
    start = time.time()
    b = memoryview(data)
    while b:
        b = b[1:]
    print('memoryview', n, time.time()-start)

几个内置方法用法提醒

zip()
按照位置一一合并


__import__()  --用户输入的为字符串,导入用户输入的模块
内置函数

 

3.生成器/迭代器

3.1生成器

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

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

 1 a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 2 
 3 for k,v in enumerate(a):
 4     a[k] = v +1
 5 
 6 print(a)
 7 
 8 列表生成式
 9 a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
10 a = [i+1 for i in a]
11 print(a)
12 
13 a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
14 a = [i*i if i > 5 else i for i in a]
15 print(a)
16 
17 
18 --生成器generator
19 a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
20 a = (i*i if i > 5 else i for i in a)
21 print(next(a))
22 print(a.__next__())
23 
24 fib()
25 
26 生成器 yeild保存了函数的中断状态
27 
28 def fib(max):
29     n,a,b = 0,0,1
30     while n < max:
31         yield b
32         a,b = b ,a+b
33         n += 1
34 
35     return "done"
36 
37 f = fib(15)
38 print(f.__next__())
39 print(f.__next__())
40 print("调用其他函数")
41 print(f.__next__())
42 print(f.__next__())
43 print(f.__next__())
44 print(f.__next__())

 

1 >>> L = [x * x for x in range(10)]
2 >>> L
3 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
4 >>> g = (x * x for x in range(10))
5 >>> g
6 <generator object <genexpr> at 0x1022ef630>

创建Lg的区别仅在于最外层的[]()L是一个list,而g是一个generator。

我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?

如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:

1 >>> next(g)
2 0
3 >>> next(g)
4 1

我们讲过,generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

当然,上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:

 1 >>> g = (x * x for x in range(10))
 2 >>> for n in g:
 3 ...     print(n)
 4 ...
 5 0
 6 1
 7 4
 8 9
 9 16
10 25
11 36
12 49
13 64
14 81

 

所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

1 def fib(max):
2     n, a, b = 0, 0, 1
3     while n < max:
4         print(b)
5         a, b = b, a + b
6         n = n + 1
7     return 'done'

 

注意,赋值语句:

1 a, b = b, a + b
2 
3 相当于:
4 
5 t = (b, a + b) # t是一个tuple
6 a = t[0]
7 b = t[1]

 

但不必显式写出临时变量t就可以赋值。

上面的函数可以输出斐波那契数列的前N个数:

 1 >>> fib(10)
 2 1
 3 1
 4 2
 5 3
 6 5
 7 8
 8 13
 9 21
10 34
11 55
12 done

 

仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

 1 def fib(max):
 2     n,a,b = 0,0,1
 3 
 4     while n < max:
 5         #print(b)
 6         yield  b
 7         a,b = b,a+b
 8 
 9         n += 1
10 
11     return 'done'

 

这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

1 >>> f = fib(6)
2 >>> f
3 <generator object fib at 0x104feaaa0>

 

这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

 1 data = fib(10)
 2 print(data)
 3 
 4 print(data.__next__())
 5 print(data.__next__())
 6 print("干点别的事")
 7 print(data.__next__())
 8 print(data.__next__())
 9 print(data.__next__())
10 print(data.__next__())
11 print(data.__next__())
12 
13 #输出
14 <generator object fib at 0x101be02b0>
15 1
16 干点别的事
17 3
18 8

 

在上面fib的例子,我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代:

1 >>> for n in fib(6):
2 ...     print(n)
3 ...
4 1
5 3
6 8

 

 但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIterationvalue中:

 1 >>> g = fib(6)
 2 >>> while True:
 3 ...     try:
 4 ...         x = next(g)
 5 ...         print('g:', x)
 6 ...     except StopIteration as e:
 7 ...         print('Generator return value:', e.value)
 8 ...         break
 9 ...
10 g: 1
11 g: 1
12 g: 2
13 g: 3
14 g: 5
15 g: 8
16 Generator return value: done

 

还可通过yield实现在单线程的情况下实现并发运算的效果

#_*_coding:utf-8_*_
__author__ = 'Alex Li'

import time
def consumer(name):
    print("%s 准备吃包子啦!" %name)
    while True:
       baozi = yield

       print("包子[%s]来了,被[%s]吃了!" %(baozi,name))


def producer(name):
    c = consumer('A')
    c2 = consumer('B')
    c.__next__()
    c2.__next__()
    print("老子开始准备做包子啦!")
    for i in range(10):
        time.sleep(1)
        print("做了2个包子!")
        c.send(i)
        c2.send(i)

producer("alex")

通过生成器实现协程并行运算
模拟并发

 

3.2迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如listtupledictsetstr等;一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。可以使用isinstance()判断一个对象是否是Iterable对象:

 

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
View Code

 

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

可以使用isinstance()判断一个对象是否是Iterator对象:

1 >>> from collections import Iterator
2 >>> isinstance((x for x in range(10)), Iterator)
3 True
4 >>> isinstance([], Iterator)
5 False
6 >>> isinstance({}, Iterator)
7 False
8 >>> isinstance('abc', Iterator)
9 False

生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

listdictstrIterable变成Iterator可以使用iter()函数:

 

1 >>> isinstance(iter([]), Iterator)
2 True
3 >>> isinstance(iter('abc'), Iterator)
4 True

 

你可能会问,为什么listdictstr等数据类型不是Iterator

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

 

小结

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:

 1 for x in [1, 2, 3, 4, 5]:
 2     pass
 3 
 4 实际上完全等价于:
 5 
 6 # 首先获得Iterator对象:
 7 it = iter([1, 2, 3, 4, 5])
 8 # 循环:
 9 while True:
10     try:
11         # 获得下一个值:
12         x = next(it)
13     except StopIteration:
14         # 遇到StopIteration就退出循环
15         break

 

4.常用模块

4.1time &datetime模块

 1 #_*_coding:utf-8_*_
 2 __author__ = 'Alex Li'
 3 
 4 import time
 5 
 6 
 7 # print(time.clock()) #返回处理器时间,3.3开始已废弃 , 改成了time.process_time()测量处理器运算时间,不包括sleep时间,不稳定,mac上测不出来
 8 # print(time.altzone)  #返回与utc时间的时间差,以秒计算\
 9 # print(time.asctime()) #返回时间格式"Fri Aug 19 11:14:16 2016",
10 # print(time.localtime()) #返回本地时间 的struct time对象格式
11 # print(time.gmtime(time.time()-800000)) #返回utc时间的struc时间对象格式
12 
13 # print(time.asctime(time.localtime())) #返回时间格式"Fri Aug 19 11:14:16 2016",
14 #print(time.ctime()) #返回Fri Aug 19 12:38:29 2016 格式, 同上
15 
16 
17 
18 # 日期字符串 转成  时间戳
19 # string_2_struct = time.strptime("2016/05/22","%Y/%m/%d") #将 日期字符串 转成 struct时间对象格式
20 # print(string_2_struct)
21 # #
22 # struct_2_stamp = time.mktime(string_2_struct) #将struct时间对象转成时间戳
23 # print(struct_2_stamp)
24 
25 
26 
27 #将时间戳转为字符串格式
28 # print(time.gmtime(time.time()-86640)) #将utc时间戳转换成struct_time格式
29 # print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #将utc struct_time格式转成指定的字符串格式
30 
31 
32 
33 
34 
35 #时间加减
36 import datetime
37 
38 # print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925
39 #print(datetime.date.fromtimestamp(time.time()) )  # 时间戳直接转成日期格式 2016-08-19
40 # print(datetime.datetime.now() )
41 # print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
42 # print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
43 # print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
44 # print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分
45 
46 
47 #
48 # c_time  = datetime.datetime.now()
49 # print(c_time.replace(minute=3,hour=2)) #时间替换

 

 





4.2random模块
 1 import random
 2 print random.random()
 3 print random.randint(1,2)
 4 print random.randrange(1,10)
 5 
 6 
 7 生成随机验证码
 8 
 9 import random
10 checkcode = ''
11 for i in range(4):
12     current = random.randrange(0,4)
13     if current != i:
14         temp = chr(random.randint(65,90))
15     else:
16         temp = random.randint(0,9)
17     checkcode += str(temp)
18 print checkcode

 

4.3os模块

 1 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
 2 os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
 3 os.curdir  返回当前目录: ('.')
 4 os.pardir  获取当前目录的父目录字符串名:('..')
 5 os.makedirs('dirname1/dirname2')    可生成多层递归目录
 6 os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
 7 os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
 8 os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
 9 os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
10 os.remove()  删除一个文件
11 os.rename("oldname","newname")  重命名文件/目录
12 os.stat('path/filename')  获取文件/目录信息
13 os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
14 os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
15 os.pathsep    输出用于分割文件路径的字符串
16 os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
17 os.system("bash command")  运行shell命令,直接显示
18 os.environ  获取系统环境变量
19 os.path.abspath(path)  返回path规范化的绝对路径
20 os.path.split(path)  将path分割成目录和文件名二元组返回
21 os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
22 os.path.basename(path)  返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
23 os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
24 os.path.isabs(path)  如果path是绝对路径,返回True
25 os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
26 os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
27 os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
28 os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
29 os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间

 

4.4sys模块

1 sys.argv           命令行参数List,第一个元素是程序本身路径
2 sys.exit(n)        退出程序,正常退出时exit(0)
3 sys.version        获取Python解释程序的版本信息
4 sys.maxint         最大的Int值
5 sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
6 sys.platform       返回操作系统平台名称
7 sys.stdout.write('please:')
8 val = sys.stdin.readline()[:-1]


4.5json和pickle模块

用于序列化的两个模块

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换

Json模块提供了四个功能:dumps、dump、loads、load

pickle模块提供了四个功能:dumps、dump、loads、load

 

4.6 logging

 1 import logging
 2  
 3 #create logger
 4 logger = logging.getLogger('TEST-LOG')
 5 logger.setLevel(logging.DEBUG)
 6  
 7  
 8 # create console handler and set level to debug
 9 ch = logging.StreamHandler()
10 ch.setLevel(logging.DEBUG)
11  
12 # create file handler and set level to warning
13 fh = logging.FileHandler("access.log")
14 fh.setLevel(logging.WARNING)
15 # create formatter
16 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
17  
18 # add formatter to ch and fh
19 ch.setFormatter(formatter)
20 fh.setFormatter(formatter)
21  
22 # add ch and fh to logger
23 logger.addHandler(ch)
24 logger.addHandler(fh)
25  
26 # 'application' code
27 logger.debug('debug message')
28 logger.info('info message')
29 logger.warn('warn message')
30 logger.error('error message')
31 logger.critical('critical message')

 





posted @ 2017-02-22 10:23  春野之火  阅读(579)  评论(0编辑  收藏  举报