一.变量
变量:变量的概念基本上和初中代数的方程变量是一致的,只是在计算机程序中,变量不仅可以是数字,还可以是任意数据类型。
变量在程序中就是用一个变量名表示了,变量名必须是大小写英文、数字和_
的组合,且不能用数字开头
在Python中,等号=
是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,例如:
1 a = 123 # a是整数2 print(a)3 a = 'ABC' # a变为字符串4 print(a)
上节知识回顾
字符串
数字 列表 元组 字典a.可变与不可变 1.可变:列表,字典 2.不可变:字符串,数字,元祖b.访问顺序 1.顺序访问:字符串,列表,元祖 2.映射:字典 3.直接访问:数字c.存放元素个数 1.容器类型:列表,元组,字典 2.字符串,数字,
二.集合
1.集合定义
集合:集合是基本的数学概念,它是集合论的研究对象,指具有某种特定性质的事物的总体,(在最原始的集合论─朴素集合论─中的定义,集合就是“一堆东西”。)集合里的事物(“东西”),叫作元素。若然 x 是集合 A 的元素,记作 x ∈ A。
(1)
在 Python 中,集合分为两类:
- set:可变集合
- frozenset:不可变集合
set 可以原地修改,或者说是可变的,也可以说是 unhashable(不可哈希)的。
frozenset,顾名思义,是一个被“冻结”的集合,不能原地修改,是 hashable(可哈希)的。
(2)
在 Python 中,集合由内置的 set 类型定义。
要创建集合,需要将所有项(元素)放在花括号({}
)内,以逗号(,
)分隔。
1 >>> s = { 'P', 'y', 't', 'h', 'o', 'n'}2 >>> type(s)3
集合可以有任意数量的元素,它们可以是不同的类型(例如:数字、元组、字符串等)。但是,集合不能有可变元素(例如:列表、集合或字典)。
1 >>> s = {1, 2, 3} # 整形的集合2 >>> 3 >>> s = {1.0, 'Python', (1, 2, 3)} # 混合类型的集合4 >>> 5 >>> s = set(['P', 'y']) # 从列表创建6 >>>7 >>> s = {1, 2, [3, 4]} # 不能有可变元素8 ...9 TypeError: unhashable type: 'list'
创建空集合比较特殊。在 Python 中,空花括号({}
)用于创建空字典。要创建一个没有任何元素的集合,使用 set() 函数(不要包含任何参数)。
1 >>> d = {} # 空字典2 >>> type(d)34 >>> 5 >>> s = set() # 空集合6 >>> type(s)7
2.集合特性:
1.不同元素组成
2.无序3.集合中元素必须是不可变类型# 无序性>>> s = set('Python')>>> s{ 'y', 'n', 'h', 'o', 'P', 't'}>>>>>> s[0] # 不支持索引...TypeError: 'set' object does not support indexing# 互异性>>> s = set('Hello')>>> s{ 'e', 'H', 'l', 'o'}# 确定性>>> 'l' in sTrue>>> >>> 'P' not in sTrue
3.集合运算
集合之间也可进行数学集合运算(例如:并集、交集等),可用相应的操作符或方法来实现。
考虑 A、B 两个集合,进行以下操作。
1 A = set('abcd')2 B = set('cdef')
1.子集
子集,为某个集合中一部分的集合,故亦称部分集合。
使用操作符 <
执行子集操作,同样地,也可使用方法 issubset() 完成。
1 C = set('ab') 2 C < A3 True4 5 C < B6 False7 8 C.issubset(A)9 True
2.并集
一组集合的并集是这些集合的所有元素构成的集合,而不包含其他元素。
使用操作符 |
执行并集操作,同样地,也可使用方法 union() 完成。
# #求并集
#print(p_s.union(l_s))
#print(p_s|l_s)
1 >>> A | B2 { 'e', 'f', 'd', 'c', 'b', 'a'}3 >>> 4 >>> A.union(B)5 { 'e', 'f', 'd', 'c', 'b', 'a'}
3.交集
两个集合 A 和 B 的交集是含有所有既属于 A 又属于 B 的元素,而没有其他元素的集合。
使用 &
操作符执行交集操作,同样地,也可使用方法 intersection() 完成。
# #求交集 # print(p_s,l_s) # print(p_s.intersection(l_s)) # print(p_s&l_s)
1 >> A & B2 { 'd', 'c'}3 >>> 4 >>> A.intersection(B)5 { 'd', 'c'}
4.差集
A 与 B 的差集是所有属于 A 且不属于 B 的元素构成的集合
使用操作符 -
执行差集操作,同样地,也可使用方法 difference() 完成。
# #求差集 # print('差集',p_s-l_s) # print(p_s.difference(l_s)) # print('差集',l_s-p_s) # print(l_s.difference(p_s))
1 >>> A - B2 { 'b', 'a'}3 >>> 4 >>> A.difference(B)5 { 'b', 'a'}
5.对称差
两个集合的对称差是只属于其中一个集合,而不属于另一个集合的元素组成的集合。
使用 ^
操作符执行差集操作,同样地,也可使用方法 symmetric_difference() 完成。
1 >>> A ^ B2 { 'b', 'e', 'f', 'a'}3 >>> 4 >>> A.symmetric_difference(B)5 { 'b', 'e', 'f', 'a'}
6.更改集合
虽然集合不能有可变元素,但是集合本身是可变的。也就是说,可以添加或删除其中的元素。
可以使用 add() 方法添加单个元素,使用 update() 方法添加多个元素,update() 可以使用元组、列表、字符串或其他集合作为参数。
1 >>> s = { 'P', 'y'} 2 >>> 3 >>> s.add('t') # 添加一个元素 4 >>> s 5 { 'P', 'y', 't'} 6 >>> 7 >>> s.update(['h', 'o', 'n']) # 添加多个元素 8 >>> s 9 { 'y', 'o', 'n', 't', 'P', 'h'}10 >>> 11 >>> s.update(['H', 'e'], { 'l', 'l', 'o'}) # 添加列表和集合12 >>> s13 { 'H', 'y', 'e', 'o', 'n', 't', 'l', 'P', 'h'}
7.从集合中删除
可以使用 discard() 和 remove() 方法删除集合中特定的元素。
两者之间唯一的区别在于:如果集合中不存在指定的元素,使用 discard() 保持不变;但在这种情况下,remove() 会引发 KeyError。
1 s = {'P', 'y', 't', 'h', 'o', 'n'} 2 s.discard('t') # 去掉一个存在的元素 3 4 s{'y', 'o', 'n', 'P', 'h'} 5 s.remove('h') # 删除一个存在的元素 6 7 s{'y', 'o', 'n', 'P'} 8 s.discard('w') # 去掉一个不存在的元素(正常) 9 10 s{'y', 'o', 'n', 'P'}11 s.remove('w') # 删除一个不存在的元素(引发错误)
类似地,可以使用 pop() 方法删除和返回一个项目。
还可以使用 clear() 删除集合中的所有元素。
>>> s = set('Python')>>> >>> s.pop() # 随机返回一个元素'y'>>> >>> s.clear() # 清空集合>>> s set()
集合的方法
方法 | 描述 |
---|---|
add() | 将元素添加到集合中 |
clear() | 删除集合中的所有元素 |
copy() | 返回集合的浅拷贝 |
difference() | 将两个或多个集合的差集作为一个新集合返回 |
difference_update() | 从这个集合中删除另一个集合的所有元素 |
discard() | 删除集合中的一个元素(如果元素不存在,则不执行任何操作) |
intersection() | 将两个集合的交集作为一个新集合返回 |
intersection_update() | 用自己和另一个的交集来更新这个集合 |
isdisjoint() | 如果两个集合有一个空交集,返回 True |
issubset() | 如果另一个集合包含这个集合,返回 True |
issuperset() | 如果这个集合包含另一个集合,返回 True |
pop() | 删除并返回任意的集合元素(如果集合为空,会引发 KeyError) |
remove() | 删除集合中的一个元素(如果元素不存在,会引发 KeyError) |
symmetric_difference() | 将两个集合的对称差作为一个新集合返回 |
symmetric_difference_update() | 用自己和另一个的对称差来更新这个集合 |
union() | 将集合的并集作为一个新集合返回 |
update() | 用自己和另一个的并集来更新这个集合 |
集合的内置函数
函数 | 描述 |
---|---|
all() | 如果集合中的所有元素都是 True(或者集合为空),则返回 True。 |
any() | 如果集合中的所有元素都是 True,则返回 True;如果集合为空,则返回 False。 |
enumerate() | 返回一个枚举对象,其中包含了集合中所有元素的索引和值(配对)。 |
len() | 返回集合的长度(元素个数) |
max() | 返回集合中的最大项 |
min() | 返回集合中的最小项 |
sorted() | 从集合中的元素返回新的排序列表(不排序集合本身) |
sum() | 返回集合的所有元素之和 |
8.不可变集合
frozenset 是一个具有集合特征的新类,但是一旦分配,它里面的元素就不能更改。这一点和元组非常类似:元组是不可变的列表,frozenset 是不可变的集合。
集合是 unhashable 的,因此不能用作字典的 key;而 frozensets 是 hashable 的,可以用作字典的 key。
可以使用函数 frozenset() 创建 frozenset。
1 >>> s = frozenset('Python')2 >>> type(s)3
frozenset 也提供了一些列方法,和 set 中的类似。
1 >>> dir(frozenset)2 ['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'copy', 'difference', 'intersection', 'isdisjoint', 'issubset', 'issuperset', 'symmetric_difference', 'union']
由于 frozenset 是不可变的,所以没有添加或删除元素的方法。
三.字符串格式化
字符串格式化:Python的字符串格式化有两种方式: 百分号方式、format方式
百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存。[]
1.百分号的方式
%[(name)][flags][width].[precision]typecode
- (name) 可选,用于选择指定的key
- flags 可选,可供选择的值有:
- + 右对齐;正数前加正好,负数前加负号;
- - 左对齐;正数前无符号,负数前加负号;
- 空格 右对齐;正数前加空格,负数前加负号;
- 0 右对齐;正数前无符号,负数前加负号;用0填充空白处
- width 可选,占有宽度
- .precision 可选,小数点后保留的位数
- typecode 必选
- s,获取传入对象的__str__方法的返回值,并将其格式化到指定位置
- r,获取传入对象的__repr__方法的返回值,并将其格式化到指定位置
- c,整数:将数字转换成其unicode对应的值,10进制范围为 0 <= i <= 1114111(py27则只支持0-255);字符:将字符添加到指定位置
- o,将整数转换成 八 进制表示,并将其格式化到指定位置
- x,将整数转换成十六进制表示,并将其格式化到指定位置
- d,将整数、浮点数转换成 十 进制表示,并将其格式化到指定位置
- e,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)
- E,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)
- f, 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)
- F,同上
- g,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)
- G,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)
- %,当字符串中存在格式化标志时,需要用 %%表示一个百分号
注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式
常用格式化:(重要)
1 tpl = "i am %s" % "alex" 2 3 tpl = "i am %s age %d" % ("alex", 18) 4 5 tpl = "i am %(name)s age %(age)d" % { "name": "alex", "age": 18} 6 7 tpl = "percent %.2f" % 99.97623 8 9 tpl = "i am %(pp).2f" % { "pp": 123.425556, }10 11 tpl = "i am %.2f %%" % { "pp": 123.425556, }
2、Format方式
[[fill]align][sign][#][0][width][,][.precision][type]
-
- fill 【可选】空白处填充的字符
- align 【可选】对齐方式(需配合width使用)
- <,内容左对齐
- >,内容右对齐(默认)
- =,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。 即使:符号+填充物+数字
- ^,内容居中
- sign 【可选】有无符号数字
- +,正号加正,负号加负;
- -,正号不变,负号加负;
- 空格 ,正号空格,负号加负;
- # 【可选】对于二进制、八进制、十六进制,如果加上#,会显示 0b/0o/0x,否则不显示
- , 【可选】为数字添加分隔符,如:1,000,000
- width 【可选】格式化位所占宽度
- .precision 【可选】小数位保留精度
- type 【可选】格式化类型
- 传入” 字符串类型 “的参数
- s,格式化字符串类型数据
- 空白,未指定类型,则默认是None,同s
- 传入“ 整数类型 ”的参数
- b,将10进制整数自动转换成2进制表示然后格式化
- c,将10进制整数自动转换为其对应的unicode字符
- d,十进制整数
- o,将10进制整数自动转换成8进制表示然后格式化;
- x,将10进制整数自动转换成16进制表示然后格式化(小写x)
- X,将10进制整数自动转换成16进制表示然后格式化(大写X)
- 传入“ 浮点型或小数类型 ”的参数
- e, 转换为科学计数法(小写e)表示,然后格式化;
- E, 转换为科学计数法(大写E)表示,然后格式化;
- f , 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
- F, 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
- g, 自动在e和f中切换
- G, 自动在E和F中切换
- %,显示百分比(默认显示小数点后6位)
- 传入” 字符串类型 “的参数
常用格式化:(重要)
1 tpl = "i am {}, age {}, {}".format("seven", 18, 'alex') 2 3 tpl = "i am {}, age {}, {}".format(*["seven", 18, 'alex']) 4 5 tpl = "i am {0}, age {1}, really {0}".format("seven", 18) 6 7 tpl = "i am {0}, age {1}, really {0}".format(*["seven", 18]) 8 9 tpl = "i am {name}, age {age}, really {name}".format(name="seven", age=18)10 11 tpl = "i am {name}, age {age}, really {name}".format(**{ "name": "seven", "age": 18})12 13 tpl = "i am {0[0]}, age {0[1]}, really {0[2]}".format([1, 2, 3], [11, 22, 33])14 15 tpl = "i am {:s}, age {:d}, money {:f}".format("seven", 18, 88888.1)16 17 tpl = "i am {:s}, age {:d}".format(*["seven", 18])18 19 tpl = "i am {name:s}, age {age:d}".format(name="seven", age=18)20 21 tpl = "i am {name:s}, age {age:d}".format(**{ "name": "seven", "age": 18})22 23 tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)24 25 tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)26 27 tpl = "numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}".format(15)28 29 tpl = "numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}".format(num=15)
更多格式化操作:https://docs.python.org/3/library/string.html
四.函数
1. 函数知识体系
1 什么是函数?2 为什么要用函数?3 函数的分类:内置函数与自定义函数4 如何自定义函数 语法 定义有参数函数,及有参函数的应用场景 定义无参数函数,及无参函数的应用场景 定义空函数,及空函数的应用场景5 调用函数 如何调用函数 函数的返回值 函数参数的应用:形参和实参,位置参数,关键字参数,默认参数,*args,**kwargs6 高阶函数(函数对象)7 函数嵌套8 作用域与名称空间9 装饰器10 迭代器与生成器及协程函数11 三元运算,列表解析、生成器表达式12 函数的递归调用13 内置函数14 面向过程编程与函数式编程
2.数学定义的函数与python中的函数
初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域
例如y=2*x
python中函数定义:函数是逻辑结构化和过程化的一种编程方法。
1 python中函数定义方法: 2 3 def test(x): 4 "The function definitions" 5 x+=1 6 return x 7 8 def:定义函数的关键字 9 test:函数名10 ():内可定义形参11 "":文档描述(非必要,但是强烈建议为你的函数添加描述信息)12 x+=1:泛指代码块或程序处理逻辑13 return:定义返回值调用运行:可以带参数也可以不带函数名()
补充:
1.编程语言中的函数与数学意义的函数是截然不同的俩个概念,编程语言中的函数是通过一个函数名封装好一串用来完成某一特定功能的逻辑,数学定义的函数就是一个等式,等式在传入因变量值x不同会得到一个结果y,这一点与编程语言中类似(也是传入一个参数,得到一个返回值),不同的是数学意义的函数,传入值相同,得到的结果必然相同且没有任何变量的修改(不修改状态),而编程语言中的函数传入的参数相同返回值可不一定相同且可以修改其他的全局变量值(因为一个函数a的执行可能依赖于另外一个函数b的结果,b可能得到不同结果,那即便是你给a传入相同的参数,那么a得到的结果也肯定不同)
2.函数式编程就是:先定义一个数学函数(数学建模),然后按照这个数学模型用编程语言去实现它。至于具体如何实现和这么做的好处,且看后续的函数式编程。
3.为何使用函数
现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码
1while True: 2 if cpu利用率 > 90%: 3 #发送邮件提醒 4 连接邮箱服务器 5 发送邮件 6 关闭连接 7 8 if 硬盘使用空间 > 90%: 9 #发送邮件提醒10 连接邮箱服务器11 发送邮件12 关闭连接13 14 if 内存占用 > 80%:15 #发送邮件提醒16 连接邮箱服务器17 发送邮件18 关闭连接
上面的代码实现了功能,但即使是邻居老王也看出了端倪,老王亲切的摸了下你家儿子的脸蛋,说,你这个重复代码太多了,每次报警都要重写一段发邮件的代码,太low了,这样干存在2个问题:
- 代码重复过多,一个劲的copy and paste不符合高端程序员的气质
- 如果日后需要修改发邮件的这段代码,比如加入群发功能,那你就需要在所有用到这段代码的地方都修改一遍
你觉得老王说的对,你也不想写重复代码,但又不知道怎么搞,老王好像看出了你的心思,此时他抱起你儿子,笑着说,其实很简单,只需要把重复的代码提取出来,放在一个公共的地方,起个名字,以后谁想用这段代码,就通过这个名字调用就行了,如下
def 发送邮件(内容) #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: 发送邮件('CPU报警') if 硬盘使用空间 > 90%: 发送邮件('硬盘报警') if 内存占用 > 80%: 发送邮件('内存报警')
你看着老王写的代码,气势恢宏、磅礴大气,代码里透露着一股内敛的傲气,心想,老王这个人真是不一般,突然对他的背景更感兴趣了,问老王,这些花式玩法你都是怎么知道的? 老王亲了一口你儿子,捋了捋不存在的胡子,淡淡的讲,“老夫,年少时,师从京西沙河淫魔银角大王 ”, 你一听“银角大王”这几个字,不由的娇躯一震,心想,真nb,怪不得代码写的这么6, 这“银角大王”当年在江湖上可是数得着的响当当的名字,只可惜后期纵欲过度,卒于公元2016年, 真是可惜了,只留下其哥哥孤守当年兄弟俩一起打下来的江山。 此时你看着的老王离开的身影,感觉你儿子跟他越来越像了。。。
总结使用函数的好处:
1.代码重用
2.保持一致性,易维护
3.可扩展性
4.函数和过程
过程定义:过程就是简单特殊没有返回值的函数
这么看来我们在讨论为何使用函数的的时候引入的函数,都没有返回值,没有返回值就是过程,没错,但是在python中有比较神奇的事情
1def test01(): 2 msg='hello The little green frog' 3 print msg 4 5 def test02(): 6 msg='hello WuDaLang' 7 print msg 8 return msg 9 10 11 t1=test01()12 13 t2=test02()14 15 16 print 'from test01 return is [%s]' %t117 print 'from test02 return is [%s]' %t2
总结:当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,
所以在python中即便是过程也可以算作函数。
1 def test01(): 2 pass 3 4 def test02(): 5 return 0 6 7 def test03(): 8 return 0,10,'hello',['alex','lb'],{ 'WuDaLang':'lb'} 9 10 t1=test01()11 t2=test02()12 t3=test03()13 14 15 print 'from test01 return is [%s]: ' %type(t1),t116 print 'from test02 return is [%s]: ' %type(t2),t217 print 'from test03 return is [%s]: ' %type(t3),t3
总结:
返回值数=0:返回None
返回值数=1:返回object
返回值数>1:返回tuple
5.函数参数
1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
3.位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定
#位置参数,必须一一对应,缺一不行多一也不行# test(1,2,3)#关键字参数,无须一一对应,缺一不行多一也不行# test(y=1,x=3,z=4)#位置参数必须在关键字参数左边# test(1,y=2,3)#报错# test(1,3,y=2)#报错# test(1,3,z=2)# test(1,3,z=2,y=4)#报错# test(z=2,1,3)#报错
4.默认参数
# def handle(x,type='mysql'):# print(x)# print(type)# handle('hello')# handle('hello',type='sqlite')# handle('hello','sqlite')# def install(func1=False,func2=True,func3=True):# pass
5.参数组
def test(x,*args): print(x) print(args) # test(1) # test(1,2,3,4,5) # test(1,{'name':'alex'}) # test(1,['x','y','z']) # test(1,*['x','y','z']) # test(1,*('x','y','z')) # def test(x,**kwargs): # print(x) # print(kwargs) # test(1,y=2,z=3) # test(1,1,2,2,2,2,2,y=2,z=3) # test(1,y=2,z=3,z=3)#会报错 :一个参数不能传两个值 def test(x,*args,**kwargs): print(x) print(args,args[-1]) print(kwargs,kwargs.get('y')) # test(1,1,2,1,1,11,1,x=1,y=2,z=3) #报错 # test(1,1,2,1,1,11,1,y=2,z=3) # test(1,*[1,2,3],**{'y':1})