1.迭代
1.定义
如果给定一个list或tuple,我们可以通过for
循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。
2.迭代方式
在Python中,迭代是通过for ... in
来完成的
Python的for
循环不仅可以用在list或tuple上,还可以作用在其他可迭代对象上。
只要是可迭代对象,无论有无下标,都可以迭代,比如dict就可以迭代,
但因为dict的存储不是按照list的方式顺序排列,所以,迭代出的结果顺序很可能不一样。
默认情况下,dict迭代的是key。
dict={'a':1,'b':2,'c':3} for key in dict: print(key)
如果要同时迭代key和value,可以用for k, v in d.items():
。
dict={'a':1,'b':2,'c':3} for key,value in dict.items(): print(value)
由于字符串也是可迭代对象,因此,也可以作用于for
循环:
str='abc' for k in str: print(k)
3.判断是否可以迭代
方法是通过collections模块的Iterable类型判断:
from collections import Iterable print( isinstance('abc', Iterable)) # str是否可迭代 print(isinstance([1,2,3], Iterable)) # list是否可迭代 print(isinstance(123, Iterable)) # 整数是否可迭代)
总结:常见的数据类型,除了整形数和bool类型,其他均可迭代
4.迭代知识补充
如果要对 list 实现类似 Java 那样的下标循环怎么办?
python内置的枚举方法enumerate,把一个 list 变成索引元素对(枚举)
for i, value in enumerate(['A', 'B', 'C']): print (i, value)
2.列表生成式
列表生成式是Python 内置的非常简单却强大的可以用来创建 list的生成式
1.基本语法
[变量表达式 for 变量 in 表达式 ]
变形:
1). [i**2 for i in range(2,10,2) ]
2). [fun(i) for i in range(2,10,2)]
3). [i**2 for i in range(2,10,2) if i%3==0]
4). [fun(i) for i in range(2,10,2) if i%3==0]
5). [fun(i) for i in range(2,10,2) if isFun(i)]
6). [fun1(i) isFun(i) else fun2(i) for i in range(2,10,2)]
例: a = [x ** 2 for x in range(1, 10)] b = [x * x for x in range(1, 11) if x % 2 == 0] c = [m + n for m in 'ABC' for n in '123'] d = {'Java': "99", 'C': "99", 'C++': "99"} L = [k + '=' + v for k, v in d.items()] print(a) print(b) print(c) print(L)
2.练习
1. 找出1~10之间所有偶数, 并且返回一个列表, (包含以这个偶数为半径的圆的面积)
1)一般代码
import math li = [] for r in range(2,11,2): #[2,4,6,8,10] square = math.pi * r * r li.append(square) print(li)
2)列表生成式
import math print([math.pi*i*i for i in range(2,11,2)])
3) 列表生成式实现, 将要返回的操作抽象为一个函数
import math def s(r): ss=math.pi*r*r return ss print([s(r) for r in range(2,11,2)])
2. 找出1~100之间所有的质数.
判断num是否为质数, 如果为质数, 返回True, 否则返回False;
什么是质数?
只能被1和本身整除的数, 就是质数.
方法:循环:
依次判断num能否被(2,num)整除,
如果能被其中一个数整除,不是质数.
当循环结束, 都没有发现能被整除的数, 那么就是质数.
def isPrime(num): for i in range(2, num): if num % i == 0: return False else: return True print([i for i in range(2, 101) if isPrime(i)])
3. 找出1~100之间所有奇数, 并且返回一个列表,
(如果能被3整除, 返回返回该数的平方, 否则返回该数的三次方)
print([i*i if i%3==0 else i*i*i for i in range(1,100,2) ])
4.实现矩阵转置
1)列表生成式
li=[ [1,2,3], [4,5,6], [7,8,9] ] print([[n[i] for n in li] for i in range(3)])
2)内置zip
li=[ [1,2,3], [4,5,6], [7,8,9] ] print(list(zip(*li)))
3.字典生成式
1.基本语法
{key:value for 变量 in 表达式}
2.练习
1. 假设有20个学生,学生分数在60-100之间,筛选出成绩在90分以上的学生
import random stuInfo = {"westos"+ str(i):random.randint(60,100) for i in range(20)} print({ name:score for name, score in stuInfo.items() if score > 90 })
2.将字典的key值和value值调换
d = {'a':'apple', 'b':'bob', 'c':'come'} print({v:k for k,v in d.items()})
3..大小写计数合并 : key值最终全部为小写
d1 = {'A':10, 'b':3, 'a':5, 'B':8, 'd':1} print({k.lower(): d1.get(k.upper(),0)+d1.get(k.lower(),0) for k,v in d1.items()})
3.集和生成式
1.基本语法
{表达式 for 变量 in 表达式}
2.练习
求1~7的平方
s = {1,2,3,4,5,6,7} # 集合生成式 print({i**2 for i in s })
通过运行结果发现,集和是无序的
4.生成器
1.为什么需要生成器
通过列表生成式,我们可以直接创建一个列表,受到内存限制,列表容量肯定是有限的
创建一个包含 100 万个元素的列表,占用很大的存储空间;
2.定义
在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的 list,从而节省大量的空间。
在 Python 中,这种一边循环一边计算的机制,称为生成器(Generator)
3.怎么创建生成器
1)生成器最快实现的方式:通过列表生成式改写,把一个列表生成式的 [] 改成 (). 一边循环, 一边计算的机制.
例:判断2~num之间有多少个质数
def isPrime(num):
for i in range(2, num):
if num % i == 0:
return False
else:
return True
primeLi = (i for i in range(2,10) if isPrime(i))
print(primeLi)
我们会发现,使用生成器后打印出来的是一个生成器对象
2)使用yield方法
在一个一般函数中使用yield
关键字,可以实现一个最简单的生成器,此时这个函数变成一个生成器函数。yield
与return
返回相同的值,区别在于return
返回后,函数状态终止,而yield
会保存当前函数的执行状态,在返回后,函数又回到之前保存的状态继续执行。
def fun(): print('step 1') yield "yield1" print('step 2') yield 'yield2' print('step3') yield 'yield3' g = fun() print(g) ###函数中有yield, 返回值是一个生成器. next(g) #####生成器函数默认不执行函数内容, 当next(g)时, 才执行函数内容. #####执行函数时, 一直执行, 遇到yield停止。 默认情况不会显示yield后面的内容,print(next(g)) #### 如果要显示print(next(g))
4.读取内容
1)next方法
每执行一次next方法,就会生成一次运行的结果,不会一次性全出结果
def isPrime(num): for i in range(2, num): if num % i == 0: return False else: return True primeLi = (i for i in range(2,10) if isPrime(i)) print(primeLi) print(next(primeLi)) print(next(primeLi))
2)使用for循环
def isPrime(num): for i in range(2, num): if num % i == 0: return False else: return True primeLi = (i for i in range(2,10) if isPrime(i)) print(primeLi) for x in primeLi: print(x)
我们会发现,一次遍历了所有结果
5.给生成器传值
f.send(' '), 给生成器传递值;
给yield所在位置发送一个数据, 直到遇到下一个yield停止.
例:实现迷你机器人聊天
def chat_robot(): res = '' while True: receive = yield res if 'age' in receive: res = "年龄保密" elif 'name' in receive: res = "siri" else: res = "i don't know what you say" def main(): # 生成器对象 Robot = chat_robot() next(Robot) while True: send_data = input("粉条>>:") if send_data == 'q' or send_data == 'bye': print("不聊了, 我也撤了.....") break print(Robot.send(send_data)) main()
5.练习
1.斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)
以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,
斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)
在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963年起出版了以
《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。
def fib(num): """num表示将来显示几个fib数列""" a,b,count = 0,1,0 # count代表显示的已经 # a代表第一个数, b代表第二个数, count代表已经显示的fib个数,当前为0. while count < num: # 如果当前显示的个数小于需要显示的格式, 则显示b, 并且计算出下一个要显示的数。 yield b a, b = b, a+b count += 1 # 已经显示的次数加1; # 生成器: 如果函数中有yield, 那么这个函数的返回值就是一个生成器; res=fib(100) print(next(res)) print(next(res))
###或者for循环
for x in res
print(x)
生成器fib()执行的过程分析:
# 执行语句 f = fab(100) 时,并不会马上执行 fib() 函数的代码块,而是首先返回一个 iterable 对象(即生成器)!
# 在 for 循环语句执行时或者next(),才会执行 fib() 函数的代码块。
# 执行到语句 yield b 时,fib() 函数会返回一个迭代值,直到下次迭代前,
# 程序会回到 yield b 的下一条语句继续执行,然后再次回到 for 循环,如此迭代直到结束。
# 看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
# 由此可以看出,生成器通过关键字 yield 不断的将迭代器返回到内存进行处理,而不会一次性的将对象全部放入内存,
# 从而节省内存空间。
2.yield实现python3中的range
def myRange(start, stop, step=1): while stop > start: yield start start = start + step g = myRange(1,10,2) for i in g: print(i)
3.合法IP判断
"""
题目描述:
现在IPV4下用一个32位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成一个无符号整数(因此不需要用正号出现),如10.137.17.1,是我们非常熟悉的IP地址,一个IP地址串中没有空格出现(因为要表示成一个32数字)。
现在需要你用程序来判断IP是否合法。
输入描述:
输入一个ip地址
输出描述:
返回判断的结果YES or NO
示例1:
输入
10.138.15.1
输出
YES
1)正向思维
ip=input('请输入要判定的ip:') li=(ip.split('.')) if len(li) != 4: print('NO') exit() else: for i in li: if int(i)>0 and int(i)<255: pass else: print('NO') break else: print('OK')
2)逆向思维
ip=input('请输入要判定的ip:') li=(ip.split('.')) if len(li) != 4: print('NO') exit() else: for i in li: if int(i)<=0 or int(i)>=257: print('NO') exit() else: print("YES")
4.密码验证合格程序
题目描述: 密码要求
1.长度超过8位
2.包括大小写字母.数字.其它符号,以上四种至少三种
3.不能有相同长度超2的子串重复
说明:长度超过2的子串
输入描述:
一组或多组长度超过2的子符串。每组占一行
输出描述:
如果符合要求输出:OK,否则输出NG
def checklen(s): if len(s) > 8: return True else: return False def check2(s): flag_up, flag_low, flag_digit, flag_other = 0, 0, 0, 0 for i in s: if i.isupper(): flag_up = 1 elif i.islower(): flag_low = 1 elif i.isdigit(): flag_digit = 1 else: flag_other = 1 if (flag_up + flag_low + flag_digit + flag_other) >= 3: return True else: return False def check3(s): for i in range(len(s) - 3): if s.count(s[i:i + 3]) > 1: return False return True while True: s = input() if s == 'quit': break if checklen(s) and check2(s) and check3(s): print ("OK") else: print ("NG")