(董付国)Python 学习笔记---Python控制结构(2)

3.3.1 for循环与while循环

  • Python提供了两种基本循环结构语句——while语句、for语句。
  • while一般用于循环次数难以确定的情况下。
  • for循环一般用于循环次数可以提前确定的情况,尤其是用于枚举序列或迭代对象中的元素。
  • 一般优先考虑使用for循环。
  • 相同或不同的循环结构之间可以相互嵌套,实现更为复杂的逻辑。

3.3.2 循环结构的优化

  • 为了优化程序以获得更高的效率和运行速度,在编写循环语时:1.尽量减少循环内部不必要的计算;2.将与循环变量无关的代码尽可能地提取到循环之外;3对于多重嵌套,尽量减少内层循环中不必要的计算,尽可能往外提。

  • 优化前的代码:

import time
digits = (1,2,3,4)
start = time.time()

for i in range(1000):
    result = []
    for i in digits:
        for j in digits:
            for k in digits:
                result.append(i*100+j*10+k)
print(result,time.time()-start)
[111, 112, 113, 114, 121, 122, 123, 124, 131, 132, 133, 134, 141, 142, 143, 144, 211, 212, 213, 214, 221, 222, 223, 224, 231, 232, 233, 234, 241, 242, 243, 244, 311, 312, 313, 314, 321, 322, 323, 324, 331, 332, 333, 334, 341, 342, 343, 344, 411, 412, 413, 414, 421, 422, 423, 424, 431, 432, 433, 434, 441, 442, 443, 444] 
0.07795858383178711
  • 优化后的代码:
import time
digits = (1,2,3,4)
start = time.time()

for i in range(1000):
    result = []
    for i in digits:
        i=i*100
        for j in digits:
            j=j*10
            for k in digits:
                result.append(i+j+k)
print(result,time.time()-start)
  • 另外,在循环中应尽量引用局部变量,因为局部变量的查询和访问速度比全局变量略快,在使用模块中的方法时,可以通过将其转换为局部变量来提高运行速度。
import time
import math

start = time.time()                     #获取当前时间
for i in range(10000000):
    math.sin(i)
print('Time Used:',time.time()-start)   #输出所用时间

loc_sin = math.sin                      #引入局部变量
start = time.time()
for i in range(10000000):
    loc_sin(i)
print('Time Used:',time.time()-start)
[111, 112, 113, 114, 121, 122, 123, 124, 131, 132, 133, 134, 141, 142, 143, 144, 211, 212, 213, 214, 221, 222, 223, 224, 231, 232, 233, 234, 241, 242, 243, 244, 311, 312, 313, 314, 321, 322, 323, 324, 331, 332, 333, 334, 341, 342, 343, 344, 411, 412, 413, 414, 421, 422, 423, 424, 431, 432, 433, 434, 441, 442, 443, 444] 
0.06296038627624512
Time Used: 9.541480541229248
Time Used: 8.620984315872192

3.4 break和continue语句

  • break语句在while循环和for循环中都可以使用,一般放在if选择结构中,一旦break语句被执行,将使得整个循环提前结束。
  • continue语句的作用是终止当前循环,并忽略continue之后的语句,然后回到循环的顶端,提前进入下一次循环。
  • 除非break语句让代码更简单,更清晰,否则不要轻易使用。
    下面的代码用来计算小于100的最大素数,注意break语句和else子句的用法。
>>> for n in range(1100,1,-1):
...     for i in range(2,n):
...             if n%i == 0:
...                     break
...     else:
...             print(n)
...             break
...
1097
  • 每次进入循环时的i已经不再是上一次的i,所以修改其值并不会影响循环的执行。
for i in range(7):
    print(id(i),':',i)
140703268303072 : 0
140703268303104 : 1
140703268303136 : 2
140703268303168 : 3
140703268303200 : 4
140703268303232 : 5
140703268303264 : 6

3.5 案例精选

例 3-4:计算1+2+3+…+100的值。

s = 0
for i in range(1,101):
    s = s+i

print('1+2+3+...+100 = ',s)
print('1+2+3+...+100 = ',sum(range(1,101)))

例 3-5:输出序列中的元素。

a_list = ['a','b','mpilgrim','z','example']
for i,v in enumerate(a_list):
    print('列表的第',i+1,'个元素是:',v)
print(list(enumerate(a_list)))

例 3-6:求1~100之间能被7整除,但不能同时被5整除的所有整数。

for i in range(1,101):
    if i%7 == 0 and i%5 != 0:
            print(i)

例 3-7:输出“水仙花数”。所谓水仙花数是指1个3位的十进制数,其各位数字的立方和等于该数本身。例如:153=1^3 + 5^ 3+3^3。

for i in range(100,1000):
    #这里是序列解包用法
    bai,shi,ge = map(int,str(i))
    if i == bai**3+shi**3+ge**3:
        print(i)

例 3-8:打印九九乘法表。

for i in range(1,10):
    for j in range(1,i+1):
        print('{0}*{0}={0}'.format(i,j,i*j).ljust(6),end = ',')
    print()     #起换行作用,没有定义默认换行

例 3-9:判断一个数是否为素数。

import math

while True:
n = input('Input an inter:')
n = int(n)
#Math.ceil() 函数返回大于或等于一个给定数字的最小整数
m = math.ceil(math.sqrt(n)+1)   
for i in range(2,m):
    if n%i == 0 and i<n:
        print('No')
        break
else:
    print('Yes')
    print('Yes')

例 3-10:编写程序,输出由1,2,3,4这四个数字组成的每位数不相同的三位数。

  • 使用集合实现同样功能
def demo(data,k = 3):
    data = set(data)
    for i in data:
        if i == 0:continue      #0不能做百位
        ii = i*100
        for j in data - {i}:
            jj = j*10
            for k in data - {i,j}:
                print(ii+jj+k)

例 3-11:生成一个含有20个随机数的列表,要求所有元素不相同,并且每个元素的值介于1-100之间。

import random

x = []
while True:
    if len(x)==20:break
    n = random.randint(1,100)
    if n not in x:
        x.append(n)
print(x)
print(len(x))
print(sorted(x))
  • 用集合做,会更简单一些
from random import randint

x = set()
while len(x)<20:
    x.add(randint(1,100))
print(x)
print(sorted(x))
>>> import random
>>> random.sample(range(1,101),20)
[47, 42, 15, 56, 11, 6, 50, 48, 2, 87, 89, 25, 90, 3, 75, 58, 33, 26, 37, 57]

例 3-12:编写程序,计算组合数C(n,i),从n个元素中任选i个,有多少种选法。

def Cni1(n,i):
    if not (isinstance(n,int) and isinstance(i,int) and n>=i):
        print('n and i must be integers and n must be larger them or equal to i.')
        return
    result = 1
    Min,Max = sorted((i,n-i))
    for i in range(n,0,-1):
        if i>Max:
            result*=i
        elif i<=Min: 
            result/=i
    return result

print(Cni1(8,3))
  • 也可以使用math库中的阶乘函数直接按组合数定义实现。
>>> def Cni2(n,i):
...     import math
...     return int(math.factorial(n)/math.factorial(i)/math.factorial(n-i))
...
>>> Cni2(8,3)
56
  • 还可以直接使用Python标准库itertools提供的函数。
import itertools
print(len(tuple(itertools.combinations(range(1,9),3))))

注:不太建议这样写,太占用内存
itertools还提供了排列函数permutations()。

>>> import itertools
>>> for item in itertools.permutations(range(1,4),2):
...     print(item)
...
(1, 2)
(1, 3)
(2, 1)
(2, 3)
(3, 1)
(3, 2)

itertools还提供了用于循环遍历可迭代对象元素的函数cycle()。

>>> import itertools
>>> x = 'Pravate Key'
>>> y = itertools.cycle(x)              #循环遍历序列中的元素
>>> for i in range(20):
...     print(next(y),end=',')
...
P,r,a,v,a,t,e, ,K,e,y,P,r,a,v,a,t,e, ,K,>>>
>>> for i in range(5):
...     print(next(y),end=',')
...
e,y,P,r,a,>>>

itertools还提供了根据一个序列的值对另一序列进行过滤的函数compress()。

>>> x = range(1,20)
>>> y = (1,0)*9+(1,)
>>> y
(1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
>>> list(itertools.compress(x,y))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

itertools还提供了根据函数返回值对序列进行分组的函数groupby()。

import itertools
def group(v):
    if v > 10:
        return 'greater than 10'
    elif v < 5:
        return 'less than 5'
    else:
        return 'between 5 and 10'
x = range(20)
y = itertools.groupby(x,group)
#根据函数返回值对序列元素进行分组
#y生成了一个字典,group是键,x就是值
for k,v in y:
    print(k,':',list(v))
posted @ 2019-08-11 20:00  旅人_Eric  阅读(264)  评论(0编辑  收藏  举报