python_day5

时间:2017-06-02 23:37:30   收藏:0   阅读:394

python协程函数、递归、匿名函数与内置函数使用、模块与包

目录:

一、协程函数(yield生成器用法二)

1、生成器的语句形式

a.生成器相关python函数、装饰器、迭代器、生成器,我们是如何使用生成器的。一个生成器能暂停执行并返回一个中间的结果这就是 yield 语句的功能 : 返回一个中间值给调用者并暂停执行。

我们的调用方式为yeild 1的方式,此方式又称为生成器的语句形式。

而使用生成器的场景:使用生成器最好的场景就是当你需要以迭代的方式去穿越一个巨大的数据集合。比如:一个巨大的文件/一个复杂的数据库查询等。

技术分享
 1 # def read_file(fpath):
 2 #     BLOCK_SIZE = 1024
 3 #     with open(fpath, rb) as f:
 4 #         while True:
 5 #             block = f.read(BLOCK_SIZE)
 6 #             if block:
 7 #                 yield block
 8 #             else:
 9 #                 return
10 
11 ‘‘‘
12 结果:
13     以上传入参数就可以按1024字符,以迭代的方式,返回读取内容,内存只占1024字符
14 ‘‘‘
View Code

b.加强的生成器特性:

除了可以使用 next() 方法来获取下一个生成的值,用户还可以使用 send() 方法将一个新的或者是被修改的值返回给生成器。除此之外,还可以使用 close() 方法来随时退出生成器。

技术分享
 1 ‘‘‘
 2 b.加强的生成器特性
 3 除了可以使用 next() 方法来获取下一个生成的值,用户还可以使用 send() 方法将一个新
 4 的或者是被修改的值返回给生成器。除此之外,还可以使用 close() 方法来随时退出生成器。 
 5 ‘‘‘
 6 # def eater(name):
 7 #     print(%s ready to eat!!! % (name))
 8 #     count = 1
 9 #     while True:
10 #         yield count
11 #         count += 1
12 #         print(%s eating % (name))
13 # 
14 # g = eater(Tom)
15 # print(next(g))
16 # print(next(g))
17 ‘‘‘
18 直接运行g.send()报错,为生成器没有初始化,所以使用.send(),第一个值必须初始化
19 Traceback (most recent call last):
20   File "D:/old_boy/old_boy_17_05/yield_ex1.py", line 66, in <module>
21     print(g.send(shuyang))
22 TypeError: cant send non-None value to a just-started generator
23 # print(g.send(shuyang)) 
24 ‘‘‘
25 # print(g.send(None))  # .send(None) == next(g)
26 # print(g.send(None))
27 # g.close()  # 退出生成器
28 # next(g)
29 ‘‘‘
30 结果:
31 Tom ready to eat!!!
32 1
33 Tom eating
34 2
35 Tom eating
36 3
37 Tom eating
38 4
39 Traceback (most recent call last):
40   File "D:/old_boy/old_boy_17_05/yield_ex1.py", line 62, in <module>
41     next(g)
42 StopIteration
43 ‘‘‘
View Code

直接运行g.send()会报错,为生成器没有初始化,所以使用.send(),第一次必须使用.send(None)初始化生成器

2、生成器的表达式形式

a.简单用法,其实x = yield,就是一个表达式,yield不仅仅是一个语句,它还可以用.send()特性,做赋值操作。

技术分享
 1 # # 装饰器,执行生成器第一次初始化
 2 # def deco(func):
 3 #     def wrapper(*args,**kwargs):
 4 #         res=func(*args,**kwargs)
 5 #         next(res)
 6 #         return res
 7 #     return wrapper
 8 #
 9 # @deco
10 # def eater(name):
11 #     print(%s ready to eat!!! % name)
12 #     while True:
13 #         food = yield
14 #         print(%s eating %s % (name, food))
15 #
16 # g = eater(alex11)
17 # # next(g) # g.send(None)
18 # g.send(面条)
19 # g.send(馒头)
20 # g.send(包子)
21 
22 ‘‘‘
23 结果:
24 alex11 ready to eat!!!
25 alex11 eating 面条
26 alex11 eating 馒头
27 alex11 eating 包子
28 ‘‘‘
View Code

b.通过生成式表达式优化列表解析:两者的语法非常相似,但生成器表达式返回的不是一个列表类型对象,而是一个生成器对象,生成器是一个内存使用友好的结构。

列表解析:

[expr for iter_var in iterable if cond_expr]

生成器表达式:

(expr for iter_var in iterable if cond_expr)

技术分享
 1 # 列表写法
 2 l = [egg%s %i for i in range(10)]
 3 print(l)
 4 # 生成器写法
 5 g = (egg%s %i for i in range(10))
 6 # print(g)
 7 # print(next(g))
 8 # print(next(g))
 9 # for i in g:
10 #     print(i)
11 print(list(g))
12 ‘‘‘
13 结果:
14 [egg0, egg1, egg2, egg3, egg4, egg5, egg6, egg7, egg8, egg9]
15 [egg0, egg1, egg2, egg3, egg4, egg5, egg6, egg7, egg8, egg9]
16 ‘‘‘
View Code
技术分享
 1 # 文件写法
 2 # 列表存值写法
 3 # f = open(FILENAME, r)
 4 # allLinesLen = [line(x.strip()) for x in f]
 5 # f.close()
 6 # return max(allLinesLen)   # 返回列表中最大的数值
 7 # 生成器存值写法
 8 # f = open(FILENAME, r)
 9 # allLinesLen = (line(x.strip()) for x in f)   # 这里的 x 相当于 yield x
10 # f.close()
11 # return max(allLinesLen)
View Code

3、协程函数

  在python中,协程函数就是使用了yield表达式形式的生成器。

  它的优点为省内存,没有锁的概念、利用if判断,执行效率高。此概念主要应用在用户态线程中。

技术分享
 1 ‘‘‘
 2 3、协程函数
 3   协程函数就是使用了yield表达式形式的生成器
 4 ‘‘‘
 5 def deco(func):
 6     def warrper(*args, **kwargs):
 7         res = func(*args, **kwargs)
 8         res.send(None)  # 初始化生成器
 9         return res
10     return warrper
11 
12 @deco
13 def eater(name):
14     print(%s ready to eat!!! % name)
15     food_list = []
16     while True:
17         food = yield food_list
18         # 因yield,程序在这里停顿,所以,要添加yield返回值操作,必须在yield后
19         food_list.append(food)
20         print(%s eating %s % (name, food))
21 
22 g = eater(alex)
23 #next(g)  # g.send(None)
24 print(g.send(面条))
25 print(g.send(馒头))
26 print(g.send(包子))
27 
28 ‘‘‘
29 结果:
30 alex ready to eat!!!
31 alex eating 面条
32 [面条]
33 alex eating 馒头
34 [面条, 馒头]
35 alex eating 包子
36 [面条, 馒头, 包子]
37 ‘‘‘
View Code

ps.协程的概念:

为了进一步减小内核态线程上下文切换的开销,于是又有了用户态线程设计,即纤程(Fiber)。如果连时钟阻塞、 线程切换这些功能我们都不需要了,自己在进程里面写一个逻辑流调度的东西。那么我们即可以利用到并发优势,又可以避免反复系统调用,还有进程切换造成的开销,分分钟给你上几千个逻辑流不费力。这就是用户态线程。

4、协程函数示例:仿grep -rl ‘python’ /root

技术分享
  1 #!/usr/bin/env python
  2 # -*- coding:utf-8 -*-
  3 
  4 ‘‘‘
  5 yield的应用场景
  6 grep -rl python /root
  7 ‘‘‘
  8 import os
  9 
 10 def init(func):
 11     def wrapper(*args, **kwargs):
 12         res = func(*args, **kwargs)
 13         next(res)
 14         return res
 15     return wrapper
 16 
 17 # 第一个@init必须写,否则生成器无法完成全部代码的初始化
 18 @init
 19 def search(target):
 20     ‘‘‘
 21     拼接字符串
 22     :param target: 生成器内存地址
 23     :return: 
 24     ‘‘‘
 25     while True:
 26         search_path = yield
 27         # os.walk() 方法用于通过在目录树种游走输出在目录中的文件名,向上或者向下
 28         # 结果:(a, [b], [a.txt, __init__.py])(目录名,子目录,文件)
 29         g = os.walk(search_path)
 30         for par_dir, _, files in g:
 31             for file in files:
 32                 # r‘‘为原生字符串,不经过python解释器编译(windows下路径表示尤为有用)
 33                 file_abs_path = r%s\%s %(par_dir, file)
 34                 # print(file_abs_path)
 35                 # 下一层生成器
 36                 target.send(file_abs_path)
 37 @init
 38 def opener(target):
 39     ‘‘‘
 40     打开文件
 41     :param target: 生成器内存地址
 42     :return: 查看文件内容生成器发送文件地址,文件句柄
 43     ‘‘‘
 44     while True:
 45         file_abs_path = yield  # 接收search传递的路径
 46         with open(file_abs_path, encoding=utf-8) as f:
 47             #print(f)
 48             target.send((file_abs_path, f))  # send多个用元组的方式,为了把文件的路径传递下去
 49 
 50 # g = search(opener())
 51 # g.send(a)
 52 ‘‘‘
 53 结果:
 54 <_io.TextIOWrapper name=a/a.txt mode=r encoding=utf-8>
 55 <_io.TextIOWrapper name=a/__init__.py mode=r encoding=utf-8>
 56 <_io.TextIOWrapper name=a\\b/b.txt mode=r encoding=utf-8>
 57 <_io.TextIOWrapper name=a\\b/__init__.py mode=r encoding=utf-8>
 58 <_io.TextIOWrapper name=a\\b\\c/c.txt mode=r encoding=utf-8>
 59 <_io.TextIOWrapper name=a\\b\\c/__init__.py mode=r encoding=utf-8>
 60 <_io.TextIOWrapper name=a\\b\\c\\d/d.txt mode=r encoding=utf-8>
 61 <_io.TextIOWrapper name=a\\b\\c\\d/__init__.py mode=r encoding=utf-8>
 62 ‘‘‘
 63 
 64 @init
 65 def cat(target):
 66     ‘‘‘
 67     查看文件内容
 68     :param target: 生成器内存地址
 69     :return: 查找匹配line生成器,文件地址和一行内容
 70     ‘‘‘
 71     while True:
 72         file_abs_path, f = yield
 73         for line in f:
 74             tag = target.send((file_abs_path, line))
 75             # 优化函数,文件找到关键字则返回文件,tag为此标记
 76             if tag:
 77                 break
 78 
 79 @init
 80 def grep(target, pattern):
 81     ‘‘‘
 82     查找匹配line
 83     :param target: 生成器内存地址
 84     :param pattern: 查询的关键字
 85     :return: 打印行生成器,发送文件地址
 86     ‘‘‘
 87     # 优化函数,文件找到关键字则返回文件,tag为此标记
 88     tag = False
 89     while True:
 90         file_abs_path, line = yield tag
 91         # tag此标记,初始化写在yield之后
 92         tag = False
 93         if pattern in line:
 94             tag = True
 95             target.send(file_abs_path)
 96 
 97 @init
 98 def printer():
 99     ‘‘‘
100     打印行
101     :return: 
102     ‘‘‘
103     while True:
104         file_abs_path = yield
105         print(file_abs_path)
106 
107 
108 x = rD:\old_boy\old_boy_17_05\a
109 g = search(opener(cat(grep(printer(),python))))
110 print(g)
111 g.send(x)
112 
113 ‘‘‘
114 结果:
115 <generator object search at 0x0000004FFDCCB780>
116 D:\old_boy\old_boy_17_05\a\a.txt
117 D:\old_boy\old_boy_17_05\a\__init__.py
118 D:\old_boy\old_boy_17_05\a\b\b.txt
119 D:\old_boy\old_boy_17_05\a\b\__init__.py
120 D:\old_boy\old_boy_17_05\a\b\c\__init__.py
121 D:\old_boy\old_boy_17_05\a\b\c\d\d.txt
122 D:\old_boy\old_boy_17_05\a\b\c\d\__init__.py
123 ‘‘‘
View Code

ps.

a.有yield的函数,必须@init初始化(next(<g>))

b.这种写法,必须层层嵌套调用,不能漏下任何一行。

c. a目录结构:

技术分享

二、面向过程编程

  是一种流水线式的编程思路,是机械式。以上grep -rl ‘python‘ /root实例就是一个典型的面向过程编程。

1、优点:

程序的结构清晰,可以把复杂的问题简单

2、缺点:

扩展性差

3、应用场景:

linux内核,git,httpd

ps.本节只是浅浅的讨论一下,后续会有详细分析。

三、递归

递归算法是一种直接或者间接地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。

a.特点:
递归算法解决问题的特点:

ps.所以一般不提倡用递归算法设计程序。

b.要求:

递归算法所体现的“重复”一般有三个要求:

方式一:在函数调用自身

技术分享
 1 # 书写方式1:
 2 def f1():
 3     print(from f1)
 4     f1()
 5 f1()
 6 ‘‘‘
 7 结果:
 8 from f1
 9 from f1
10 from f1
11 from f1    f1()
12   File "D:/old_boy/old_boy_17_05/递归调用.py", line 32, in f1
13     f1()
14   [Previous line repeated 993 more times]
15   File "D:/old_boy/old_boy_17_05/递归调用.py", line 31, in f1
16     print(from f1)
17 RecursionError: maximum recursion depth exceeded while calling a Python object
18 递归超过文件最大限制
19 ‘‘‘
View Code

方式二:在过程里调用自身

技术分享
 1 # 书写方式2:
 2 def f1():
 3     print(f1)
 4     f2()
 5 
 6 def f2():
 7     print(f2)
 8     f1()
 9 
10 f1()
11 ‘‘‘
12 结果:
13 f1
14 f2
15 f1
16 f2
17 f1
18 f2
19 f1
20 f2
21 RecursionError: maximum recursion depth exceeded while calling a Python object
22 递归超过文件最大限制
23 ‘‘‘
View Code

 

 

 1、简单的递归示例

技术分享
import sys
# 查看当前递归最大值,默认为1000
print(sys.getrecursionlimit())
# 修改当前递归最大值
print(sys.setrecursionlimit(1000000))
print(sys.getrecursionlimit())
‘‘‘
结果:
1000
None
1000000
‘‘‘
View Code

2、递归应用之二分法

#递归应用之二分法:

技术分享
 1 #递归应用之二分法:
 2 # l = range(0,400000)
 3 l = [1, 2, 10,33,53,71,73,75,77,85,101,201,202,999,11111]
 4 
 5 def search(find_num,seq):
 6     if len(seq) == 0:
 7         print(not exists)
 8         return
 9     mid_index=len(seq)//2
10     mid_num=seq[mid_index]
11     print(seq,mid_num)
12     if find_num > mid_num:
13         #in the right
14         seq=seq[mid_index+1:]
15         search(find_num,seq)
16     elif find_num < mid_num:
17         #in the left
18         seq=seq[:mid_index]
19         search(find_num,seq)
20     else:
21         print(find it)
22 
23 search(77,l)
24 ‘‘‘
25 结果:
26 [1, 2, 10, 33, 53, 71, 73, 75, 77, 85, 101, 201, 202, 999, 11111] 75
27 [77, 85, 101, 201, 202, 999, 11111] 201
28 [77, 85, 101] 85
29 [77] 77
30 find it
31 ‘‘‘
32 # search(72,l)
33 ‘‘‘
34 结果:
35 [1, 2, 10, 33, 53, 71, 73, 75, 77, 85, 101, 201, 202, 999, 11111] 75
36 [1, 2, 10, 33, 53, 71, 73] 33
37 [53, 71, 73] 71
38 [73] 73
39 not exists
40 ‘‘‘
View Code

 

3、尾递归优化

待补全

四、匿名函数与内置函数的使用

 匿名函数就是不需要显式的指定函数,python中使用lambda 函数是一种快速定义单行的最小函数,可以用在任何需要函数的地方。

配合一些内置函数的使用,可以更加强大,但依旧为简单的函数:
支持lambda的内置函数如下:
max、min、zip、sorted
map、reduce、filter

匿名函数优点:

a. 程序一次行使用,所以不需要定义函数名,节省内存中变量定义空间
b. 如果想让程序更加简洁时。

1、常规使用

技术分享
 1 # 正常函数
 2 def func(x,y):
 3     return x+y
 4 print(func(1,2))
 5 ‘‘‘
 6 结果:
 7 3
 8 ‘‘‘
 9 
10 
11 # 匿名函数
12 f=lambda x,y:x+y
13 print(f)
14 print(f(1,2))
15 ‘‘‘
16 结果:
17 <function <lambda> at 0x0000001C641BC8C8>
18 3
19 ‘‘‘
View Code

、max、min、zip、sort结合应用

max  max(sequence,key=<lambda 值:表达式>==func) 最大值

min   min(sequence,key=<lambda 值:表达式>==func) 最小值

zip    zip(sequence,sequence) 两个sequence的len()值必须相等,拉链函数,字典

sorted  sorted(可迭代对象,key=<lambda 值:表达式>==func,reverse=True ) 排序函数,默认从小到大,reverse反转

技术分享
 1 #max,min,zip,sorted的用法
 2 # 字典的运算:最小值,最大值,排序方法一:
 3 # salaries={
 4 # egon:3000,
 5 # alex:100000000,
 6 # wupeiqi:10000,
 7 # yuanhao:2000
 8 # }
 9 # 迭代字典,key值,默认的key值是不对的
10 salaries={
11 egon:3000,
12 alex:100000000,
13 wupeiqi:10000,
14 yuanhao:2000
15 }
16 # print(max(salaries))
17 ‘‘‘
18 结果:
19 yuanhao
20 ‘‘‘
21 # print(min(salaries))
22 ‘‘‘
23 结果:
24 alex
25 ‘‘‘
26 
27 # 迭代字典,取得指定key,因而比较的是key的最大和最小值
28 salaries={
29 egon:3000,
30 alex:100000000,
31 wupeiqi:10000,
32 yuanhao:2000
33 }
34 # print(max(salaries,key=lambda k:salaries[k]))
35 ‘‘‘
36 结果:
37 alex
38 ‘‘‘
39 # print(min(salaries,key=lambda k:salaries[k]))
40 ‘‘‘
41 结果:
42 yuanhao
43 ‘‘‘
44 
45 # 也可以通过zip的方式实现
46 # salaries={
47 # egon:3000,
48 # alex:100000000,
49 # wupeiqi:10000,
50 # yuanhao:2000
51 # }
52 # res=zip(salaries.values(),salaries.keys())
53 # # print(list(res))
54 # print(max(res))
55 ‘‘‘
56 结果:
57 (100000000, alex)
58 ‘‘‘
59 
60 # 相当于
61 # salaries={
62 # egon:3000,
63 # alex:100000000,
64 # wupeiqi:10000,
65 # yuanhao:2000
66 # }
67 # def func(k):
68 #     return salaries[k]
69 
70 # print(max(salaries,key=func))
71 
72 # sorted排序
73 # salaries={
74 # egon:3000,
75 # alex:100000000,
76 # wupeiqi:10000,
77 # yuanhao:2000
78 # }
79 # print(sorted(salaries)) #默认的排序结果是从小到大
80 # print(sorted(salaries,key=lambda x:salaries[x])) #默认的金钱排序结果是从小到大
81 # print(sorted(salaries,key=lambda x:salaries[x],reverse=True)) #默认的金钱排序结果是从大到小
82 ‘‘‘
83 结果:
84 [alex, egon, wupeiqi, yuanhao]
85 [yuanhao, egon, wupeiqi, alex]
86 [alex, wupeiqi, egon, yuanhao]
87 ‘‘‘
View Code

、map、reduce、filter结合应用

a.map  map(function, sequence[, sequence, ...]) -> list   

对sequence中的item依次执行function(item),执行结果输出为list。

技术分享
>>> map(str, range(5))           #对range(5)各项进行str操作
[0, 1, 2, 3, 4]        #返回列表
>>> def add(n):return n+n
... 
>>> map(add, range(5))           #对range(5)各项进行add操作
[0, 2, 4, 6, 8]
>>> map(lambda x:x+x,range(5))   #lambda 函数,各项+本身
[0, 2, 4, 6, 8]
>>> map(lambda x:x+1,range(10))  #lambda 函数,各项+1
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> map(add,zhoujy)            
[zz, hh, oo, uu, jj, yy]

#想要输入多个序列,需要支持多个参数的函数,注意的是各序列的长度必须一样,否则报错:
>>> def add(x,y):return x+y
... 
>>> map(add,zhoujy,Python)
[zP, hy, ot, uh, jo, yn]
>>> def add(x,y,z):return x+y+z
... 
>>> map(add,zhoujy,Python,test)     #test的长度比其他2个小
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add() takes exactly 2 arguments (3 given)

>>> map(add,zhoujy,Python,testop)
[zPt, hye, ots, uht, joo, ynp]
View Code

b.reduce  reduce(function, sequence[, initial]) -> value    

对sequence中的item顺序迭代调用function,函数必须要有2个参数。要是有第3个参数,则表示初始值,可以继续调用初始值,返回一个值。

python3中,需要python3中需要from functools import reduce才能调用

技术分享
 1 >>> def add(x,y):return x+y
 2 ... 
 3 >>> reduce(add,range(10))        #1+2+3+...+9
 4 45
 5 >>> reduce(add,range(11))        #1+2+3+...+10
 6 55
 7 >>> reduce(lambda x,y:x*y,range(1,3),5)           #lambda 函数,5是初始值, 1*2*5
 8 10
 9 >>> reduce(lambda x,y:x*y,range(1,6))             #阶乘,1*2*3*4*5
10 120
11 >>> reduce(lambda x,y:x*y,range(1,6),3)           #初始值3,结果再*3
12 360
13 >>> reduce(lambda x,y:x+y,[1,2,3,4,5,6])          #1+2+3+4+5+6
14 21
View Code

c.filter   filter(function or None, sequence) -> list, tuple, or string

对sequence中的item依次执行function(item),将执行结果为True(!=0)的item组成一个List/String/Tuple(取决于sequence的类型)返回,False则退出(0),进行过滤。

技术分享
 1 >>> def div(n):return n%2
 2 ... 
 3 >>> filter(div,range(5))                    #返回div输出的不等于0的真值
 4 [1, 3]
 5 >>> filter(div,range(10))
 6 [1, 3, 5, 7, 9]
 7 >>> filter(lambda x : x%2,range(10))        #lambda 函数返回奇数,返回列表
 8 [1, 3, 5, 7, 9]
 9 >>> filter(lambda x : not x%2,range(10))
10 [0, 2, 4, 6, 8]
11 >>> def fin(n):return n!=z                #过滤z 函数,出现z则返回False
12 ... 
13 >>> filter(fin,zhoujy)                    #z被过滤
14 houjy
15 >>> filter(lambda x : x !=z,zhoujy)     #labmda返回True值
16 houjy
17 >>> filter(lambda x : not x==z,zhoujy)  #返回:字符串
18 houjy
View Code

d.map、reduce、filter应用示例:

  实现5!+4!+3!+2!+1!

技术分享
 1 #!/usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 def add_factorial(n):
 4     empty_list=[]           #声明一个空列表,存各个阶乘的结果,方便这些结果相加
 5     for i in map(lambda x:x+1,range(n)):    #用传进来的变量(n)来生成一个列表,用map让列表都+1,eg:range(5) => [1,2,3,4,5]
 6         a=reduce(lambda x,y:x*y,map(lambda x:x+1,range(i)))   #生成阶乘,用map去掉列表中的0
 7         empty_list.append(a)            #把阶乘结果append到空的列表中
 8     return empty_list
 9 if __name__ == __main__:
10     import sys
11 #2选1
12 #(一)
13     try:
14         n = input("Enter a Number(int) : ")
15         result=add_factorial(n)   #传入变量
16         print reduce(lambda x,y:x+y,result)      #阶乘结果相加
17     except (NameError,TypeError):
18         print "That‘s not a Number!"
19 #(二)
20 #    result = add_factorial(int(sys.argv[1]))   #传入变量
21 #    print reduce(lambda x,y:x+y,result)      #阶乘结果相加
View Code

将100~200以内的质数挑选出来

技术分享
 1 ‘‘‘
 2 思路:
 3 
 4 质数是指:只有1和它本身两个因数,如2、35、7都是质数,即能被1和本身整除,1不是质数。
 5 比如一个数字N,看它是否质数的话,就要看:有没有能整除【2,N】之间的数X(不包含本身),即N%X是否为0,要是没有就为质数。
 6 所以我们要实现的算法是:拿一个数字N,去除以【2,N】之间的数X,来得到质数,即:N/2,N/3,……,N/N-2,N/N-1   ===> N/range(2,N)
 7 ‘‘‘
 8 #!/usr/bin/env python
 9 #-*- coding:utf-8 -*-
10 def is_prime(start,stop):
11     stop  = stop+1     #包含列表右边的值
12     prime = filter(lambda x : not [x%i for i in range(2,x) if x%i == 0],range(start,stop))   #取出质数,x从range(start,stop) 取的数
13     print prime
14 
15 if __name__ == __main__:
16     try :
17         start = input("Enter a start Number :")
18     except :
19         start = 2   #开始值默认2
20     try :
21         stop  = input("Enter a stop  Number :")
22     except :
23         stop  = 0   #停止数,默认0,即不返回任何值
24     is_prime(start,stop)
25 ‘‘‘
26 结果:
27 Enter a start Number :10
28 Enter a stop  Number :20
29 [11, 13, 17, 19]
30 ‘‘‘
View Code

五、模块

一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。

a.为何要使用模块?
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用。

b.模块的搜索顺序:

c.模块分为三种:

ps.需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名

1、导入模块:

示例文件spam.py(执行文件同级目录)

技术分享
 1 print(from the spam.py)
 2 money = 1000
 3 
 4 def read1():
 5     print(spam->read1->money, money)
 6 
 7 def read2():
 8     print(spam->read2->calling read1)
 9     read1()
10 
11 def change():
12     global money
13     money = 0
View Code

a.模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行.(python的内存优化手段)
b.每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突.

技术分享
 1 # 只在第一次导入时才执行spam.py内代码,此处的显式效果是只打印一次from the spam.py,当然其他的顶级代码也都被执行了,只不过没有显示效果.
 2 # import spam_mod
 3 # import spam_mod
 4 # import spam_mod
 5 # import spam_mod
 6 ‘‘‘
 7 结果:
 8 from the spam_moy.py
 9 ‘‘‘
10 
11 #测试一:money与spam.money不冲突
12 # import spam_mod
13 # money=10
14 # print(spam_mod.money)
15 ‘‘‘
16 结果:
17 from the spam_mod.py
18 1000
19 ‘‘‘
20 
21 # 测试二:read1与spam.read1不冲突
22 # import spam_mod
23 # def read1():
24 #     print(========)
25 # spam_mod.read1()
26 ‘‘‘
27 结果:
28 from the spam_mod.py
29 spam_mod->read1->money 1000
30 ‘‘‘
31 
32 # 测试三:执行spam.change()操作的全局变量money仍然是spam中的
33 # import spam_mod
34 # money=1
35 # spam_mod.change()
36 # print(money)
37 
38 ‘‘‘
39 执行结果:
40 from the spam_mod.py
41 1
42 ‘‘‘
View Code

ps.import导入时所做的事情:

1.产生新的名称空间
2.以新建的名称空间为全局名称空间,执行文件的代码
3.拿到一个模块名spam,指向spam.py产生的名称空间

对比import spam,会将源文件的名称空间‘spam‘带到当前名称空间中,使用时必须是spam.名字的方式而from 语句相当于import,也会创建新的名称空间,但是将spam中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了.

对比import:

优点:方便,不用加前缀
缺点:容易跟当前文件的名称空间冲突

技术分享
 1 # from spam import read1,read2
 2 
 3 # 测试一:导入的函数read1,执行时仍然回到spam.py中寻找全局变量money
 4 # from spam_mod import read1
 5 # money=1000
 6 # read1()
 7 ‘‘‘
 8 执行结果:
 9 from the spam.py
10 spam_mod->read1->money 1000
11 ‘‘‘
12 
13 #测试二:导入的函数read2,执行时需要调用read1(),仍然回到spam.py中找read1()
14 # from spam_mod import read2
15 # def read1():
16 #     print(==========)
17 # read2()
18 
19 ‘‘‘
20 执行结果:
21 from the spam.py
22 spam_mod->read2->calling read1
23 spam_mod->read1->money 1000
24 ‘‘‘
25 
26 # 测试三:导入的函数read1,被当前位置定义的read1覆盖掉了
27 # from spam_mod import read1
28 # def read1():
29 #     print(==========)
30 # read1()
31 ‘‘‘
32 执行结果:
33 from the spam.py
34 ==========
35 ‘‘‘
View Code

-加as,别名写法:   

from spam_mod import read1 as read

-多行写法:

from spam import (read1,

          read2,

          money)

-*写法:from spam import *, 把spam中所有的不是以下划线(_)开头的名字都导入到当前位置

技术分享
 1 # from spam import * 
 2 from spam_mod import * #将模块spam中所有的名字都导入到当前名称空间
 3 print(money)
 4 print(read1)
 5 print(read2)
 6 print(change)
 7 
 8 ‘‘‘
 9 执行结果:
10 from the spam_mod.py
11 1000
12 <function read1 at 0x1012e8158>
13 <function read2 at 0x1012e81e0>
14 <function change at 0x1012e8268>
15 ‘‘‘
View Code

ps.form ... import ...导入时所做的事情:

1.产生新的名称空间
2.以新建的名称空间为全局名称空间,执行文件的代码
3.直接拿到就是spam.py产生的名称空间中名字

2、__all__变量与__name__变量

原文:http://www.cnblogs.com/you0329/p/6935512.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!