目录
- 15,Python3 迭代器与生成器
- 15-1 迭代器
- 15-1-1 基础知识
- 15-1-2 迭代器与for循环工作原理
- 15-2 生成器(本质就是迭代器)
- 15-2-1 yield 表达式
- 15-2-2 三元表达式
- 15-2-3 列表生成式
- 15-2-4 其他生成器(——没有元祖生成式——)
- 15-2-5 二分法
- 15-2-6 匿名函数与lambdaj
- 16,Python3 函数
- 16-1 定义一个函数
- 16-2 函数调用
- 16-3 参数传递
- 16-4 可更改(mutable)与不可更改(immutable)对象
- 16-5 python 传不可变对象实例
- 16-6 传可变对象实例
- 16-7 函数参数详解
- 16-7-1 位置参数--------关键字参数---------混合使用
- 16-7-2 默认参数------位置参数与默认参数混用
- 16-7-3 可变长度的参数
- 16-7-4 函数的类型提示
- 17,Python3 数据结构
- 17-1 列表
- 17-2 将列表当做堆栈使用
- 17-3 将列表当作队列使用
- 17-4 列表推导式
- 17-5 嵌套列表解析
- 17-6 del 语句
- 17-7 元组和序列
- 17-8 集合
- 17-9 字典
- 17-10 遍历技巧
- 18,Python3 模块
- 18-1 模块
- 18-2 写模块时测试
- 18-3 from xxx import xxx
- 18-4 从一个模块导入所有
- 18-5 sys.path 模块搜索路径优先级
- 18-6 sys.modules 查看内存中的模块
- 18-7 编写规范的模块
15,Python3 迭代器与生成器
15-1 迭代器
15-1-1 基础知识
1,迭代器:迭代取值的工具,迭代是重复的过程,每一次重复都是基于上次的结果而继续的,单纯的重复不是迭代
# 可迭代对象: 但凡内置有__iter__()方法的都称之为可迭代对象
# 字符串---列表---元祖---字典---集合---文件操作 都是可迭代对象# 调用可迭代对象下的__iter__方法将其转换为可迭代对象
d = {'a':1, 'b':2, 'c':3}d_iter = d.__iter__() # 把字典d转换成了可迭代对象# d_iter.__next__() # 通过__next__()方法可以取值print(d_iter.__next__()) # a
print(d_iter.__next__()) # b
print(d_iter.__next__()) # c# 没值了以后就会报错, 抛出异常StopIteration
#-----------------------------------------------
d = {'a':1, 'b':2, 'c':3}
d_iter = d.__iter__()
while True:try:print(d_iter.__next__())except StopIteration:break
# 对同一个迭代器对象,取值取干净的情况下第二次取值的时候去不了,没值,只能造新的迭代器
15-1-2 迭代器与for循环工作原理
#可迭代对象与迭代器详解#可迭代对象:内置有__iter__() 方法对象# 可迭代对象.__iter__(): 得到可迭代对象#迭代器对象:内置有__next__() 方法# 迭代器对象.__next__():得到迭代器的下一个值# 迭代器对象.__iter__(): 得到的值迭代器对象的本身(调跟没调一个样)-----------> 为了保证for循环的工作# for循环工作原理d = {'a':1, 'b':2, 'c':3}d_iter = d.__iter__()# 1,d.__iter__() 方法得到一个跌倒器对象# 2,迭代器对象的__next__()方法拿到返回值,将该返回值赋值给k# 3,循环往复步骤2,直到抛出异常,for循环会捕捉异常并结束循坏for k in d:print(k)# 可迭代器对象不一定是迭代器对象------------迭代器对象一定是可迭代对象# 字符串---列表---元祖---字典---集合只是可迭代对象,不是迭代器对象、# 文件操作时迭代器对象也是可迭代对象
15-2 生成器(本质就是迭代器)
# 函数里包含yield,并且调用函数以后就能得到一个可迭代对象
def test():print('第一次')yield 1print('第二次')yield 2print('第三次')yield 3print('第四次')g = test()
print(g) # <generator object test at 0x0000014C809A27A0>
g_iter = g.__iter__()
res1 = g_iter.__next__() # 第一次
print(res1) # 1
res2 = g_iter.__next__() # 第二次
print(res2) # 2
res3 = g_iter.__next__() # 第三次
print(res3) # 3 # 补充
len(s) -------> s.__len__()
next(s) ------> s.__next__()
iter(d) -------> d.__iter__()
15-2-1 yield 表达式
def person(name):print("%s吃东西啦!!"%name)while True:x = yield Noneprint('%s吃东西啦---%s'%(name,x))g = person('aini')
# next(g) =============== g.send(None)
next(g)
next(g)
# send()方法可以给yield传值
# 不能在第一次运行时用g.send()来传值,需要用g.send(None)或者next(g) 来初始化,第二次开始可以用g.send("值")来传值
g.send("雪糕") # aini吃东西啦---雪糕
g.send("西瓜") # aini吃东西啦---西瓜
15-2-2 三元表达式
x = 10
y = 20
res = x if x > y else y
# 格式
条件成立时返回的值 if 条件 else 条件不成立时返回的值
15-2-3 列表生成式
l = ['aini_aaa','dilnur_aaa','donghua_aaa','egon']
res = [name for name in l if name.endswith('aaa')]
print(res)# 语法: [结果 for 元素 in 可迭代对象 if 条件]l = ['aini_aaa','dilnur_aaa','donghua_aaa','egon']
l = [name.upper() for name in l]
print(l)l = ['aini_aaa','dilnur_aaa','donghua_aaa','egon']
l = [name.replace('_aaa','') for name in l if name.endswith('_aaa')]
print(l)
15-2-4 其他生成器(——没有元祖生成式——)
### 字典生成器
keys = ['name','age','gender']
res = {key: None for key in keys}
print(res) # {'name': None, 'age': None, 'gender': None}items = [('name','aini'),('age',22),('gender','man')]
res = {k:v for k,v in items}
print(res)## 集合生成器
keys = ['name','age','gender']
set1 = {key for key in keys}## 没有元祖生成器
g = (i for i in range(10) if i % 4 == 0 ) ## 得到的是一个迭代器#### 统计文件字符个数
with open('aini.txt', mode='rt', encoding= 'utf-8') as f:res = sum(len(line) for line in f)print(res)
15-2-5 二分法
l = [-10,-6,-3,0,1,10,56,134,222,234,532,642,743,852,1431]def search_num(num,list):mid_index = len(list) // 2if len(list) == 0:print("没找到")return Falseif num > list[mid_index]:list = list[mid_index + 1 :]search_num(num,list)elif num < list[mid_index]:list = list[:mid_index]search_num(num, list)else:print('找到了' , list[mid_index])search_num(743,l)
15-2-6 匿名函数与lambdaj
## 定义
res = lambda x,y : x+y
## 调用
(lambda x,y : x+y)(10,20) # 第一种方法
res(10,20) ## 第二种方法##应用场景
salary = {'aini':20000,'aili':50000,'dilnur':15000,'hahhaha':42568,'fdafdaf':7854
}res = max(salary ,key= lambda x : salary[x])
print(res)
16,Python3 函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
16-1 定义一个函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
语法
Python 定义函数使用 def 关键字,一般格式如下:
def 函数名(参数列表):函数体
默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。
让我们使用函数来输出"Hello World!":
>>>def hello() :print("Hello World!")>>> hello()
Hello World!
>>>
更复杂点的应用,函数中带上参数变量:
#!/usr/bin/python3# 计算面积函数
def area(width, height):return width * heightdef print_welcome(name):print("Welcome", name)print_welcome("Runoob")
w = 4
h = 5
print("width =", w, " height =", h, " area =", area(w, h))
以上实例输出结果:
Welcome Runoob
width = 4 height = 5 area = 20
16-2 函数调用
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
如下实例调用了 printme() 函数:
#!/usr/bin/python3# 定义函数
def printme( str ):# 打印任何传入的字符串print (str)return# 调用函数
printme("我要调用用户自定义函数!")
printme("再次调用同一函数")
以上实例输出结果:
我要调用用户自定义函数!
再次调用同一函数
16-3 参数传递
在 python 中,类型属于对象,变量是没有类型的:
a=[1,2,3]a="Runoob"
以上代码中,[1,2,3] 是 List 类型,“Runoob” 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。
16-4 可更改(mutable)与不可更改(immutable)对象
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。
- **不可变类型:**变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。
- **可变类型:**变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
python 函数的参数传递:
- **不可变类型:**类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
- **可变类型:**类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
16-5 python 传不可变对象实例
#!/usr/bin/python3def ChangeInt( a ):a = 10b = 2
ChangeInt(b)
print( b ) # 结果是 2
实例中有 int 对象 2,指向它的变量是 b,在传递给 ChangeInt 函数时,按传值的方式复制了变量 b,a 和 b 都指向了同一个 Int 对象,在 a=10 时,则新生成一个 int 值对象 10,并让 a 指向它。
16-6 传可变对象实例
可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。例如:
#!/usr/bin/python3# 可写函数说明
def changeme( mylist ):"修改传入的列表"mylist.append([1,2,3,4])print ("函数内取值: ", mylist)return# 调用changeme函数
mylist = [10,20,30]
changeme( mylist )
print ("函数外取值: ", mylist)
传入函数的和在末尾添加新内容的对象用的是同一个引用。故输出结果如下:
函数内取值: [10, 20, 30, [1, 2, 3, 4]]
函数外取值: [10, 20, 30, [1, 2, 3, 4]]
16-7 函数参数详解
16-7-1 位置参数--------关键字参数---------混合使用
1,位置实参:在函数调用阶段, 按照从左到有的顺序依次传入的值
# 特点:按照顺序与形参一一对应2 关键字参数
# 关键字实参:在函数调用阶段,按照key=value的形式传入的值
# 特点:指名道姓给某个形参传值,可以完全不参照顺序
def func(x,y):print(x,y)func(y=2,x=1) # 关键字参数
func(1,2) # 位置参数3,混合使用,强调# 1、位置实参必须放在关键字实参前def func(x,y):print(x,y)func(1,y=2)func(y=2,1)# 2、不能能为同一个形参重复传值def func(x,y):print(x,y)func(1,y=2,x=3)func(1,2,x=3,y=4)
16-7-2 默认参数------位置参数与默认参数混用
4,默认参数# 默认形参:在定义函数阶段,就已经被赋值的形参,称之为默认参数# 特点:在定义阶段就已经被赋值,意味着在调用阶段可以不用为其赋值def func(x,y=3):print(x,y)func(x=1)func(x=1,y=44444)def register(name,age,gender='男'):print(name,age,gender)register('三炮',18)register('二炮',19) register('大炮',19)register('没炮',19,'女')5,位置形参与默认形参混用,强调:# 1、位置形参必须在默认形参的左边def func(y=2,x): # 错误写法pass# 2、默认参数的值是在函数定义阶段被赋值的,准确地说被赋予的是值的内存地址# 示范1:m=2def func(x,y=m): # y=>2的内存地址print(x,y)m=3333333333333333333func(1)# 3、虽然默认值可以被指定为任意数据类型,但是不推荐使用可变类型# 函数最理想的状态:函数的调用只跟函数本身有关系,不外界代码的影响m = [111111, ]def func(x, y=m):print(x, y)m.append(3333333)m.append(444444)m.append(5555)func(1)func(2)func(3)def func(x,y,z,l=None):if l is None:l=[]l.append(x)l.append(y)l.append(z)print(l)func(1,2,3)func(4,5,6)new_l=[111,222]func(1,2,3,new_l)
16-7-3 可变长度的参数
6,可变长度的参数(*与**的用法)# 可变长度指的是在调用函数时,传入的值(实参)的个数不固定# 而实参是用来为形参赋值的,所以对应着,针对溢出的实参必须有对应的形参来接收6.1 可变长度的位置参数# I:*形参名:用来接收溢出的位置实参,溢出的位置实参会被*保存成元组的格式然后赋值紧跟其后的形参名# *后跟的可以是任意名字,但是约定俗成应该是argsdef func(x,y,*z): # z =(3,4,5,6)print(x,y,z)func(1,2,3,4,5,6)def my_sum(*args):res=0for item in args:res+=itemreturn resres=my_sum(1,2,3,4,)print(res)# II: *可以用在实参中,实参中带*,先*后的值打散成位置实参def func(x,y,z):print(x,y,z)func(*[11,22,33]) # func(11,22,33)func(*[11,22]) # func(11,22)l=[11,22,33]func(*l)# III: 形参与实参中都带*def func(x,y,*args): # args=(3,4,5,6)print(x,y,args)func(1,2,[3,4,5,6])func(1,2,*[3,4,5,6]) # func(1,2,3,4,5,6)func(*'hello') # func('h','e','l','l','o')6.2 可变长度的关键字参数# I:**形参名:用来接收溢出的关键字实参,**会将溢出的关键字实参保存成字典格式,然后赋值给紧跟其后的形参名# **后跟的可以是任意名字,但是约定俗成应该是kwargsdef func(x,y,**kwargs):print(x,y,kwargs)func(1,y=2,a=1,b=2,c=3)# II: **可以用在实参中(**后跟的只能是字典),实参中带**,先**后的值打散成关键字实参def func(x,y,z):print(x,y,z)func(*{'x':1,'y':2,'z':3}) # func('x','y','z')func(**{'x':1,'y':2,'z':3}) # func(x=1,y=2,z=3)# 错误func(**{'x':1,'y':2,}) # func(x=1,y=2)func(**{'x':1,'a':2,'z':3}) # func(x=1,a=2,z=3)# III: 形参与实参中都带**def func(x,y,**kwargs):print(x,y,kwargs)func(y=222,x=111,a=333,b=444)func(**{'y':222,'x':111,'a':333,'b':4444})# 混用*与**:*args必须在**kwargs之前def func(x,*args,**kwargs):print(args)print(kwargs)func(1,2,3,4,5,6,7,8,x=1,y=2,z=3)def index(x,y,z):print('index=>>> ',x,y,z)def wrapper(*args,**kwargs): #args=(1,) kwargs={'z':3,'y':2}index(*args,**kwargs)# index(*(1,),**{'z':3,'y':2})# index(1,z=3,y=2)wrapper(1,z=3,y=2) # 为wrapper传递的参数是给index用的
16-7-4 函数的类型提示
## : 后面是提示信息,可以随意写
def regidter(name:"不能写艾尼",age:"至少18岁"):print(name)print(age)def register(name:str,age:int,hobbies:tuple)->int: # 返回值类型为 intprint(name)print(age)print(hobbies)# 添加提示功能的同时,再添加默认值
def register(name:str = 'aini',age:int = 18 ,hobbies:tuple)->int: # 返回值类型为 intprint(name)print(age)print(hobbies)
17,Python3 数据结构
17-1 列表
Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元组不能。
以下是 Python 中列表的方法:
下面示例演示了列表的大部分方法:
>>> a = [66.25, 333, 333, 1, 1234.5]
>>> print(a.count(333), a.count(66.25), a.count('x'))
2 1 0
>>> a.insert(2, -1)
>>> a.append(333)
>>> a
[66.25, 333, -1, 333, 1, 1234.5, 333]
>>> a.index(333)
1
>>> a.remove(333)
>>> a
[66.25, -1, 333, 1, 1234.5, 333]
>>> a.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.25]
>>> a.sort()
>>> a
[-1, 1, 66.25, 333, 333, 1234.5]
注意:类似 insert, remove 或 sort 等修改列表的方法没有返回值。
17-2 将列表当做堆栈使用
列表方法使得列表可以很方便的作为一个堆栈来使用,堆栈作为特定的数据结构,最先进入的元素最后一个被释放(后进先出)。用 append() 方法可以把一个元素添加到堆栈顶。用不指定索引的 pop() 方法可以把一个元素从堆栈顶释放出来。例如:
>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]
17-3 将列表当作队列使用
也可以把列表当做队列用,只是在队列里第一加入的元素,第一个取出来;但是拿列表用作这样的目的效率不高。在列表的最后添加或者弹出元素速度快,然而在列表里插入或者从头部弹出速度却不快(因为所有其他的元素都得一个一个地移动)。
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])
17-4 列表推导式
- 列表推导式提供了从序列创建列表的简单途径。通常应用程序将一些操作应用于某个序列的每个元素,用其获得的结果作为生成新列表的元素,或者根据确定的判定条件创建子序列。
- 每个列表推导式都在 for 之后跟一个表达式,然后有零到多个 for 或 if 子句。返回结果是一个根据表达从其后的 for 和 if 上下文环境中生成出来的列表。如果希望表达式推导出一个元组,就必须使用括号。
- 这里我们将列表中每个数值乘三,获得一个新的列表:
>>> vec = [2, 4, 6]
>>> [3*x for x in vec]
[6, 12, 18]
现在我们玩一点小花样:
>>> [[x, x**2] for x in vec]
[[2, 4], [4, 16], [6, 36]]
这里我们对序列里每一个元素逐个调用某方法:
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
我们可以用 if 子句作为过滤器:
>>> [3*x for x in vec if x > 3]
[12, 18]
>>> [3*x for x in vec if x < 2]
[]
以下是一些关于循环和其它技巧的演示:
>>> vec1 = [2, 4, 6]
>>> vec2 = [4, 3, -9]
>>> [x*y for x in vec1 for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]
>>> [x+y for x in vec1 for y in vec2]
[6, 5, -7, 8, 7, -5, 10, 9, -3]
>>> [vec1[i]*vec2[i] for i in range(len(vec1))]
[8, 12, -54]
列表推导式可以使用复杂表达式或嵌套函数:
>>> [str(round(355/113, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
17-5 嵌套列表解析
Python的列表还可以嵌套。
以下实例展示了3X4的矩阵列表:
>>> matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]
以下实例将3X4的矩阵列表转换为4X3列表:
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
以下实例也可以使用以下方法来实现:
>>> transposed = []
>>> for i in range(4):
... transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
另外一种实现方法:
>>> transposed = []
>>> for i in range(4):
... # the following 3 lines implement the nested listcomp
... transposed_row = []
... for row in matrix:
... transposed_row.append(row[i])
... transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
17-6 del 语句
使用 del 语句可以从一个列表中依索引而不是值来删除一个元素。这与使用 pop() 返回一个值不同。可以用 del 语句从列表中删除一个切割,或清空整个列表(我们以前介绍的方法是给该切割赋一个空列表)。例如:
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]
也可以用 del 删除实体变量:
>>> del a
17-7 元组和序列
元组由若干逗号分隔的值组成,例如:
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
如你所见,元组在输出时总是有括号的,以便于正确表达嵌套结构。在输入时可能有或没有括号, 不过括号通常是必须的(如果元组是更大的表达式的一部分)
17-8 集合
- 集合是一个无序不重复元素的集。基本功能包括关系测试和消除重复元素。
- 可以用大括号({})创建集合。注意:如果要创建一个空集合,你必须用 set() 而不是 {} ;后者创建一个空的字典,下一节我们会介绍这个数据结构。
以下是一个简单的演示:
>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket) # 删除重复的
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket # 检测成员
True
>>> 'crabgrass' in basket
False>>> # 以下演示了两个集合的操作
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # a 中唯一的字母
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # 在 a 中的字母,但不在 b 中
{'r', 'd', 'b'}
>>> a | b # 在 a 或 b 中的字母
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # 在 a 和 b 中都有的字母
{'a', 'c'}
>>> a ^ b # 在 a 或 b 中的字母,但不同时在 a 和 b 中
{'r', 'd', 'b', 'm', 'z', 'l'}
集合也支持推导式:
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}
17-9 字典
- 另一个非常有用的 Python 内建数据类型是字典。
- 序列是以连续的整数为索引,与此不同的是,字典以关键字为索引,关键字可以是任意不可变类型,通常用字符串或数值。
- 理解字典的最佳方式是把它看做无序的键=>值对集合。在同一个字典之内,关键字必须是互不相同。
- 一对大括号创建一个空的字典:{}。
这是一个字典运用的简单例子:
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
>>> list(tel.keys())
['irv', 'guido', 'jack']
>>> sorted(tel.keys())
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False
构造函数 dict() 直接从键值对元组列表中构建字典。如果有固定的模式,列表推导式指定特定的键值对:
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}
此外,字典推导可以用来创建任意键和值的表达式词典:
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
如果关键字只是简单的字符串,使用关键字参数指定键值对有时候更方便:
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}
17-10 遍历技巧
在字典中遍历时,关键字和对应的值可以使用 items() 方法同时解读出来:
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
... print(k, v)
...
gallahad the pure
robin the brave
在序列中遍历时,索引位置和对应值可以使用 enumerate() 函数同时得到:
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print(i, v)
...
0 tic
1 tac
2 toe
同时遍历两个或更多的序列,可以使用 zip() 组合:
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print('What is your {0}? It is {1}.'.format(q, a))
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
要反向遍历一个序列,首先指定这个序列,然后调用 reversed() 函数:
>>> for i in reversed(range(1, 10, 2)):
... print(i)
...
9
7
5
3
1
要按顺序遍历一个序列,使用 sorted() 函数返回一个已排序的序列,并不修改原值
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
... print(f)
...
apple
banana
orange
pear
18,Python3 模块
18-1 模块
## 内置模块
## 第三方模块
## 自定义模块## 模块的四种形式
1, 使用Python编写的py文件
2, 已被编译为共享库或DLL的C或C++扩展
3, 把一系列模块组织到一起的文件夹(文件夹下面有个__init__.py 该文件夹称为包)
3, 使用C编写并链接到Python解释器的内置模块import foo
## 首次导入模块会发生什么?
1,执行foo.py
2, 产生foo.py的命名空间
3,在当前文件中产生的有一个名字foo,改名字指向2中产生的命名空间## 无论是调用还是修改与源模块为准,与调用位置无关## 导入模块规范
1 Python内置模块
2,Python第三方模块
3,自定义模块## 起别名import foo as f## 自定义模块命名应该纯小写+下划线## 可以在函数内导入模块
18-2 写模块时测试
# 每个Python文件内置了__name__,指向Python文件名# 当foo.py 被运行时,
__name__ = "__main__"# 当foo.py 被当做模块导入时,
__name__ != "__main__"##### 测试时可以if判断,在foo.py文件中写以下判断
if __name__ == "__main__" :## 你的测试代码
18-3 from xxx import xxx
# from foo import x 发生什么事情
1, 产生一个模块的命名空间
2, 运行foo.py 产生,将运行过程中产生的名字都丢到命名空间去
3, 在当前命名空间拿到一个名字,改名字指向模块命名空间
18-4 从一个模块导入所有
#不太推荐使用
form foo import *
# 被导入模块有个 __all__ = []
__all__ = [] # 存放导入模块里的所有变量和函数, 默认放所有的变量和函数,也可以手动修改foo.py__all__ = ['x','change']x = 10def change():global xx = 20a = 20b = 30run.py from foo import * ## * 导入的是foo.py里的 __all__ 列表里的变量和函数print(x)change()print(a) # 会报错,因为foo.py 里的 __all__ 列表里没有a变量
18-5 sys.path 模块搜索路径优先级
1, 内存(内置模块)
2, 从硬盘查找import sys
# 值为一个列表,存放了一系列的文件夹
# 其中第一个文件夹是当前执行所在的文件夹
# 第二个文件夹当不存在,因为这不是解释器存放的,是pycharm添加的
print(sys.path)
# sys.path 里放的就是模块的存放路径查找顺序
[
'E:\\Desktop\\python全栈\\模块', 'E:\\Desktop\\python全栈', 'D:\\软件\\pycharm\\PyCharm 2021.3.1\\plugins\\python\\helpers\\pycharm_display', 'D:\\软件\\python\\python310.zip', 'D:\\软件\\python\\DLLs', 'D:\\软件\\python\\lib', 'D:\\软件\\python', 'C:\\Users\\艾尼-aini\\AppData\\Roaming\\Python\\Python310\\site-packages', 'D:\\软件\\python\\lib\\site-packages', 'D:\\软件\\python\\lib\\site-packages\\win32', 'D:\\软件\\python\\lib\\site-packages\\win32\\lib', 'D:\\软件\\python\\lib\\site-packages\\Pythonwin', 'D:\\软件\\pycharm\\PyCharm 2021.3.1\\plugins\\python\\helpers\\pycharm_matplotlib_backend'
]
18-6 sys.modules 查看内存中的模块
import sys
print(sys.module) # 是一个字典,存放导入的模块## 可以判断一个模块是否已经在内存中
print('foo' in sys.module)
18-7 编写规范的模块
"this module is used to ......" # 第一行文档注释
import sys # 导入需要用到的包
x = 1 # 定义全局变量
class foo: # 定义类pass
def test(): #定义函数passif __name__ == "__main__":pass