day11
函数式编程
函数式编程是指用一系列函数解决问题
好处:
用每一个函数完成细小的功能,一系列函数的任意组合可以完成大的问题
函数仅接收输入并产生输出,不包含任何能影响输出的内部状态
函数的可重入性
如果一个函数的输入参数一定,则返回结果必然一定的函数称为可重入函数
函数式编程的要求:
def 创建的函数最好不要访问局部作用域以外的变量,这样可以保证返回的结果的唯一性(可重入性)
高阶函数 High Order Function
满足下列条件之一:
1.函数接收一个或多个函数作为参数传入
2.函数返回一个函数
python内键的高阶函数
map , filter , sorted
map 函数
map(func, *iterables)
用函数和对可迭代对象的每一个元素作为参数计算出新的可迭代对象,当最短的一个可迭代对象不再提供数据时,此可迭代对象生成结束
示例:
# map.py
def fn(x):
return x**2
for x in map(fn,range(1, 10)):
print(x)
for x in map(lambda x:x**3, range(1, 10)):
print(x)
print(sum(map(pow, range(1, 10), range(9, 0, -1))))
filter 函数
filter(func, iterable)
筛选可迭代对象iterable中的数据,返回一个可迭代对象,此可迭代对象将对iterable进行筛选,函数func将对将对iterable中的每个元素进行求值,返回False则将此数据丢弃,返回True,则保留此数据
示例:
# filter.py
def fn(x):
if x % 2 == 0:
return True
return False
print(list(filter(fn, range(1, 21))))
sorted 函数
sorted(iterable, key=None, reverse=False)
将原可迭代对象的数据进行排序,生成排序后的列表
说明:
iteralbe 可迭代对象
key 函数是用来提供一个值,这个值将作为排序的依据
reverse 标志用来设置是否降序排序
示例:
# sorted.py
L = [5, -2, 0, 1, 3, -4]
L1 = sorted(L, key=abs, reverse=True)
print(L1) # [5, -4, 3, -2, 1, 0]
name = ['Tom','Jerry','Spike','Tyke']
print(sorted(name,key=lambda x:x[::-1])) #根据最后一个字母大小排序
#['Spike', 'Tyke', 'Tom', 'Jerry']
递归函数 recursion
函数直接或间接的调用自身
示例:
def f():
f() # 直接调用自己
f()
# 间接调用自己
def fa():
fb()
def fb():
fa()
fa()
递归说明:
递归一定要控制递归的层数,当符合一定条件时要终止递归
几乎所有的递归都能用while循环来代替
递归的优缺点:
优点:
递归把问题简单化,让思路更为清晰,代码更简洁
缺点:
递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
递归的两个阶段
递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归的终止条件
回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归到原问题求解
示例:
# mysum.py
def mysum(n):
if n == 1:
return 1
return n + mysum(n - 1)
print(mysum(100))
闭包 closure
闭包是指引用了此函数外部的变量的函数
说明:
在本质上,闭包是将内部函数和函数外部的执行环境绑定在一起的对象
条件:
1.必须有个内嵌函数
2.内嵌函数必须引用外部函数的变量
3.外部函数返回值为内嵌函数
闭包的应用:
# closure.py
def get_fx(a, b, c):
def fx(x):
return a*x**2 + b*x + c
return fx
f123 = get_fx(1, 2, 3)
print(f123(10))
1.已知五位朋友
5比4大2岁
4比3大2岁
3比2大2岁
2比1大2岁
1 10岁
打印5,3的年龄
2.已知有列表
L = [[3,5,8],10,[[13,14],15,18],20]
1)写一个函数print_list(lst) 打印出所有元素 #递归
# 3 5 8 10 13 14 ....
2) 一个函数sum_list(lst) 返回这个列表中所有元素的和
# 86
注: type(x)可以 返回变量类型
3.改写学生信息管理程序,增加
5) 按学生成绩高-低显示学生信息
6) 按学生成绩低-高显示学生信息
7) 按学生年龄高-低显示学生信息
8) 按学生年龄低-高显示学生信息
day12
装饰器 decorators(提高篇)
装饰器是一个函数,主要作用是用来包装另一个函数或类
装饰器的目的是在不改变原函数名(或类名)的情况下,改变被包装对象的行为
函数装饰器
函数装饰器指装饰器传入的是一个函数,返回的也是一个函数
语法:
def 装饰器函数名(参数):
语句块
return 函数对象
@装饰器函数名2
@装饰器函数名1
def 函数名(形参列表):
语句块
函数的文档字符串
函数内第一次未被赋值的字符串是此函数的文档字符串
语法:
def 函数名(形参列表):
"函数文档字符串"
函数语句块
说明:
文档字符串通常用来说明本函数的功能和使用方法
在交互模式下输入:help(函数名) 可以查看函数的'文档字符串'
函数文档字符串绑定在函数的 __doc__ 属性上
函数的 __doc__ 属性
用于绑定函数的文档字符串
函数定义语句(def 语句) 的完整语法
[@装饰器1]
[@装饰器2]
[...]
def 函数名([位置形参],[*元组形参],[命名关键字形参],[**字典形参]):
"""文档字符串"""
语句块
模块 Module
模块是一个包含有一系列数据、函数、类等组成规定程序组
模块是一个文件,模块文件名通常以 .py 结尾
作用:
让一些相关的数据,函数,类等有逻辑的组织在一起,使逻辑结构更加清晰
模块中的数据,函数,类等可提供给其他模块或程序使用
模块分类:
内建模块(builtins)在解释器内可以直接使用
标准库模块,安装python时已安装且可以直接使用
第三方模块(通常开源),需要自己安装
用户自己编写的模块(可以作为其他人的第三方模块)
模块的导入
import 语句
语法:
import 模块名1 [as 模块新名1], 模块名2 [as 模块新名2],...
示例:
import math
import sys, os
作用:
将某模块整体导入到当前模块中
用法:
模块名.属性名
或
模块名.函数属性名(实参传参)
如:
math.factorial(5)
dir(obj) 函数返回所有属性的字符串列表
help(obj) 函数可以查看模块的相关文档字符串
from import 语句
语法
from 模块名 import 模块属性名1 [as 属性新名1], 模块属性名2 [as 属性新名2],...
作用:
将某模块的一个或多个属性导入到当前模块的作用域
示例:
from math import *
from math import pi
from math import factorial as fac
dir 函数
dir([对象]) 返回一个字符串列表
说明:
如果没有给参数调用,则返回当前作用域内的所有变量列表
如果给定一个对象作为参数,则返回这个对象的所有变量的列表
1)对于一个模块,返回这个模块的全部属性
2)对于一个类,返回这个类的所有变量,并递归基类对象的所有变量
3)对于其他对象,返回所有变量类变量和基类变量
内建模块
math 模块
详见:
file:///home/tarena/LYZ/pbase/python_base_docs_html/%E6%95%B0%E5%AD%A6%E6%A8%A1%E5%9D%97math.html
time 模块
详见:
file:///home/tarena/LYZ/pbase/python_base_docs_html/%E6%97%B6%E9%97%B4%E6%A8%A1%E5%9D%97time.html
时间简介
公元纪年是从0000年1月1日0时开始
计算机元年是从1970年1月1日0时开始,此时时间为0,之后每过1秒时间 +1
UTC时间(Coordinated Universal Time)是从Greenwich时间开始计算的
UTC时间不会因时区问题而产生错误
DST阳光节约时间(Daylight Saving Time),又称夏时令,是一个经过日照时间修正后的时间
sys 模块
sys.path
sys.modules
sys.version
sys.version_info
sys.platform
sys.argv
sys.copyright
sys.builtin_module_names
sys.exit()
sys.getrecursionlimit()
sys.setrecursionlimit()
1.编写函数fun其功能是计算下列多项式的和
fn = 1 + 1/1! + 1/2! + ... + 1/n!
(用数学模块) 求 n = 100 时,fn 的值
2.写一个程序,以电子时钟格式:
HH:MM:SS 格式显示时间
要求每隔1秒变化1次
3.写函数f(n)求下多项式的和
Sn = 1/1 - 1/3 + 1/5 - 1/7 + .... 1/(2*n-1)
求当f(1000000) 和 f(1000000)*4
day13
自定义模块的导入
注意事项
自定义模块的文件要求以.py结尾,文件名必须标识符的规则
导入语句 import 语句等 搜索的路径顺序
import mymod
from mymod import *
搜索顺序
1.搜索程序运行时的路径(当前路径)
2.sys.path 提供的路径
sys.path 是一个列表,里面放的都是模块的搜索路径
3.搜索内建模块
设置 sys.path 路径
sys.path.append('/home/tarena')
模块的加载过程
1.在模块导入时,模块内的所有语句都会执行
2.如果一个模块已经导入,则再次导入时不会重新执行模块内的语句
模块的重新加载
import mymod
import imp
imp.reload(mymod) # 重新加载mymod模块
模块以导入和执行的过程:
1.先搜索相关的路径,找到模块名.py
2.判断是否有此模块对应的.pyc文件。如果.pyc比.py文件新,则直接加载.pyc文件
3.否则 用模块.py 文件生成 .pyc,并加载执行
pyc python的编译
编译 解释执行
mymod.py --------> mymod.pyc ---------> python3
模块的文档字符串
模块内第一个没有赋值给任何变量的字符串称为模块的文档字符串
模块的 __doc__ 属性
此属性用于绑定模块的文档字符串
模块的 __file__ 属性
此属性用于记录模块对应的文件路径
模块的 __name__ 属性
__name__ 属性用来记录模块的自身的名字
作用:
1.记录模块名
2.用来判断是否为主模块
说明:
当此模块为主模块(也就是第一个运行的模块时)运行时,__name__ 绑定 '__main__'
当此模块不是主模块时,而是被其他模块导入时,此时 __name__ 绑定模块名
模块的 __all__ 列表
模块中的 __all__ 列表是一个用来存放可导出属性的字符串列表
作用:
当用 from xxx import * 导入时,只导入__all__列表内的属性
示例:
# mymod4.py
__all__ = ['hello1','name1']
def hello1():
pass
def hello2():
pass
def hello3():
pass
name1 = 'aaa'
name2 = 'bbb'
模块的隐藏属性
模块中以'_'开头的属性,在from xxx import * 导入时,将不被导入,通常称这些属性为隐藏属性
示例:
# mymod5.py
# 此模块在用from mymod5 import * 导入时只能导入f1,name1
def f1():
pass
def _f2():
pass
def __f3():
pass
name1 = 'aaa'
_name2 = 'bbb'
随机模块 random
作用:
用于模拟或生成随机输出的模块
详见:
file:///home/tarena/LYZ/pbase/python_base_docs_html/%E9%9A%8F%E6%9C%BA%E6%A8%A1%E5%9D%97random.html
import random as R
R.random()
R.uniform(a,b)
R.randrange([start,]stop[,step])
R.choice(seq)
R.shuffle(seq[,random])
R.sample(seq,n)
包(模块包) package
包是将模块以文件夹的组织形式进行分组管理的管理方法
作用:
将一系列模块进行分类管理,有利于防止命名冲突
可以在需要时加载一个或部分模块而不是全部模块
包示例:
mypack/
__init__.py
menu.py
games/
__init__.py
contra.py
supermario.py
tanks.py
office/
word.py
excel.py
powerpoint.py
__init__.py 文件
__init__.py是常规包必须存在的文件
__init__.py会在包加载时自动调用
作用:
1.编写此包的内容
2.在内部填写文档字符串
3.在__init__.py文件内可以加载此包所依赖的一些其他模块
包的导入
同模块的导入规则
# import 语句
import 包名 [as 包新名]
import 包名.模块名 [as 模块新名]
import 包名.子包名.模块名 [as 模块新名]
# from import 语句
from 包名 import 模块名 [as 模块新名]
from 包名.子包名 import 模块名 [as 模块新名]
from 包名.子包名.模块名 import 属性名 [属性新名]
导入包时的索引路径顺序:
1.搜索程序的当前路径
2.sys.path 提供的路径
__init__.py 内的 __all__ 列表
作用:
用来记录此包中有哪些子名或模块在用from import * 语句时被导入
说明:
__all__列表只对 from xxx import * 语句起作用
包的相对导入:
包的相对导入是指包内模块的相互导入
语法:
from 相对路径包或模块 import 属性名或模块名
from 相对路径包或模块 import *
相对路径
. 代表当前路径
.. 代表上一级路径
... 代表上二级路径
.... 以此类推
注: 相对导入时不能超出包的外部
eg:
from .menu import show_menu
1.写一个闹钟程序,启动时设置定时时间
到时间后打印一句'时间到了...' 然后退出
2.模拟斗地主发牌,扑克牌共54张
黑桃('\u2660'),梅花('\u2663'),方块('\u2665'),红桃('\u2666')
A2-10JQK 大小王
三个人玩,每人17张,底牌留三张
输入回车,打印出第1个人的17张牌
输入回车,打印出第2个人的17张牌
输入回车,打印出第3个人的17张牌
输入回车,打印底牌
3.修改学生管理系统,将student_info.py 拆分为模块
要求:
1.主事件循环放在main.py中
2.show_menu 放在menu.py 中
3.与学生的操作放在student_info.py中
day14
异常(基础) except
错误是指由于逻辑或语法等导致一个程序无法正常执行的为题
异常是程序出错时标识的一种状态
当异常发生时,程序不会再向下执行,而转去调用此函数的地方待处理此错误并恢复为正常状态
异常作用:
用作信号,通知上层调用者有错误需要处理
try 语句
两张语法:
try-except语句
try-finally语句
try-except 语句语法:
try:
可能触发异常的语句
except 错误类型1 [as 变量1]:
异常处理语句1
except 错误类型2 [as 变量2]:
异常处理语句2
except (错误类型3,错误类型4,...) [as 变量3]:
异常处理语句3
...
except:
异常处理语句(其他)
else:
未发生异常语句
finally:
最终语句
作用:
尝试捕获异常,将程序由异常状态转为正常状态并正常执行
try-except 语句说明:
1.as 子句是用于绑定错误对象的变量,可以用此变量得到引发异常的原因
2.except 子句可以有一个或多个,但是至少要有一个
3.else 子句最多只能有一个,也可以省略不写
4.finally 子句最多只能有一个,也可以省略不写
5.else 子句的语句将在此try语句没有发生异常时被执行
6.finally 子句的语句在任何情况下都会被执行
python 中全部的错误类型:
参见文档:
file:///home/tarena/LYZ/pbase/python_base_docs_html/Python%E5%85%A8%E9%83%A8%E7%9A%84%E5%BC%82%E5%B8%B8%E7%B1%BB%E5%9E%8B.html
try-finally 语句
语法:
try:
可能触发异常的语句
finally:
最终语句
说明:
1.finally 子句不可以省略
2.一定不存在except子句
作用:
通常try-finally语句来做触发异常时必须要处理的事情
无论异常是否发生,finally子句都会被执行
注意:
try-finally语句不会改变程序的(正常/异常)状态
raise 语句
作用:
触发一个错误,让程序进入异常状态
发送错误通知给调用者
语法:
raise 异常类型
或
raise 异常对象
示例:
# raise.py
def make_exception():
print('函数开始')
raise ValueError
print('函数结束')
try:
make_exception()
print('make_exception调用结束')
except ValueError as e:
print('接收到ValueError类型的异常通知')
print('错误对象是', e)
assert 语句(断言语句)
语法:
assert 真值表达式, 错误数据(通常是字符串)
作用:
当真值表达式为False时,用错误数据创建一个AssertionError类型的错误,并进入异常状态
等同于:
if 真值表达式 == False:
raise AssertionError(错误数据)
示例:
# assert.py
def get_score():
s = int(input('请输入学生成绩'))
assert 0 <= s <= 100, '成绩超出范围'
return s
score = get_score()
print('学生成绩为', score)
小结:
异常处理语句(四条):
try-except 语句
用于接收异常通知,捕获异常
try-finally 语句
执行必须要执行的语句
raise 语句
发送异常通知,并进入异常状态
assert 语句
根据条件选择性的发送AssertionError类型的异常通知
为什么要异常处理机制:
在程序调用层数较深时,向主调函数传递错误信息需要层层return返回比较麻烦,用异常处理机制可以较简单的传送错误信息
图形用户界面
tkinter
1.一个球从100米高空落下,每次落地反弹的高度是原高度的一半,再落下
1)写程序算出皮球在第10次落地后反弹的高度是多高
2)打印出球经过了多少米路程
2.分解质因数,输入一个正整数,分解质因数
如:
输入 90 --> 2*3*3*5
质因数是指最小能被原整数整除的素数(不包括1)
3.修改原学生信息管理程序,加入异常处理语句,让程序在任何情况下都能按逻辑正常执行
day15
迭代器 Iterator
迭代器是访问迭代对象的工具
迭代器是用 iter(obj) 函数返回的对象(实例)
迭代器可以用next(it) 函数获取可迭代对象的数据
迭代器函数 iter和next
iter(iterable) 从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象
next(iterable) 从迭代器iterator中获取下一个记录,如果无法获取下一条记录,则触发StopIteration异常
说明:
迭代器只能向前取值,不会后退
用iter函数可以返回一个可迭代对象的迭代器
作用:
迭代器对象能用next函数获取下一个元素
示例:
L = [2, 3, 5, 7]
it = iter(L) # 用L对象返回能访问L的迭代器
生成器 Generator (python2.5版本之后)
生成器是能够动态提供数据的对象,生成器对象也是可迭代对象(实例)
生成器有两种:
1.生成器函数
2.生成器表达式
生成器函数的定义:
含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象
yield 翻译为(产生或生成)
yield 语句
语法:
yield 表达式
说明:
yield 用于 def 函数中,目的是将此函数作用生成器函数使用
yield 用来生成数据,提供迭代器的next(it)函数使用
示例:
# myyield.py
def myyield:
yield 2
yield 3
yield 5
yield 7
print('生成结束')
for x in myyield():
print(x)
生成器函数说明:
生成器函数的调用将返回一个生成器对象,生成器对象是一个可迭代对象
在生成器函数调用return会触发一个StopIteration异常
生成器表达式:
语法:
(表达式 for 变量 in 可迭代对象 [if 真值表达式])
说明:
if 子句可以省略
作用:
用推导式的形式创建一个新的生成器
迭代工具函数
迭代工具函数的作用是生成一个个性化的可迭代对象
zip(iter1[,iter2[,...]])
返回一个zip 对象,此对象用于生成元组,此元组的个数有最小的可迭代对象决定
enumerate(iterable[,start])
生成带索引的枚举对象,返回迭代类型为索引-值对(index-value对),默认索引从0开始,也可以从start指定
示例:
numbers = [10086, 10000, 10010, 95588]
names = ['中国移动', '中国电信', '中国联通']
for t in zip(numbers, names):
print(t)
d = dict(zip(numbers, names))
names = ['中国移动', '中国电信', '中国联通']
for x in enumerate(names):
print(x)
字节串和字节数组
字节串 bytes (也叫字节序列)
作用:
存储以字节为单位的数据
字节串是不可变的字节序列
字节:
字节是由8个位(bit)组成的数据单位,是计算机进行数据管理的单位
字节是用 0~255 范围内的整数表示的
创建空字节串的字面值
B = b''
B = b""
B = b''''''
B = b""""""
创建非空字节字面值
B = b'ABCD'
B = b"abcd"
B = b"""\x41\x42""""
字节串的构造函数 bytes
bytes() 生成一个空的字节串,等同于 b''
bytes(整数可迭代对象) # 用可迭代对象初始化一个字节串
bytes(整数n) 生成 n个值为0的字节串
bytes(字符串, encoding='utf-8') 用字符串转为编码生成一个字节串
bytes 运算
+ += * *=
< <= > >= == !=
索引 / 切片
in / not in
len(x)
max(x)
min(x)
sum(x)
any(x)
all(x)
bytes 和 str 的区别
bytes 存储字节(通常在 0~255) # 字节 00000000-11111111
str 存储unicode字符(通常在 0~65535)
bytes 与 str 的转换
编码(encode)
str -----------------> bytes
b = s.encode(encoding='utf-8')
解码(decode)
bytes ---------------> str
b = s.decode(encoding='utf-8')
字节数组 bytearray
可变的字节序列
字节数组的构造函数: bytearray
bytearray()
bytearray(整数)
bytearray(整型可迭代对象)
bytearray(字符串,encoding='utf-8')
bytearray 运算
+ += * *=
< <= > >= == !=
索引 / 切片
(字节数组支持索引和切片的赋值操作,规则同列表的索引和切片复制规则)
in / not in
len(x)
max(x)
min(x)
sum(x)
any(x)
all(x)
bytearray 方法:
ba.clear() 清空
ba.append(n) 追加一个字节(0-255整数)
ba.remove(value) 删除第一个出现的value,如果没有触发ValueError
ba.reverse() 字节顺序反转
ba.decode(encoding='utf-8') 解码为字符串
ba.find(sub[,start[,end]]) 查找 sub
1.写一个生成器函数primes生成素数,
此生成器函数为 primes(begin, end)
[x for x in primes(10, 20)] # [11,13,17,19]
2.写一个生成器函数,生成斐波那契数列的前n个
1 1 2 3 4 5 13
def fibonacci(n):
...
for x in fibonacci(20):
print(x)
print(sum(fibonacci(40)))
3.打印杨辉三角(6层)
1
1 2 1
1 3 3 1
1 4 6 4 1
1510 10 5 1