assertTrue 判断表达式是否为真
assertAlmostEqual 判断是否约等
assertIn 在字符串里
assertIs 判断是否为同一引用
assertEqual 判断值是否相等
assertIsNone 返回值是否为空
assertIsInstance 判断是否是某类型的实例(e.g. str)
assertGreater 是否大于
assertTrue 判断表达式是否为真
assertAlmostEqual 判断是否约等
assertIn 在字符串里
assertIs 判断是否为同一引用
assertEqual 判断值是否相等
assertIsNone 返回值是否为空
assertIsInstance 判断是否是某类型的实例(e.g. str)
assertGreater 是否大于
测试级别:
单元测试:对代码的基本单元(函数,方法)的cesh
集成测试
系统测试
验收测试
回归测试
错误异常处理
错误类型
1. 语法错误
2. 语义错误
3. 逻辑错误
异常处理
1. SyntaxError:语法错误(拼写问题等)
2. ZeroDivisionError: 处理异常
3. AttributeError: 属性异常
try:
x = 5/2
except 错误类型 as e: ('程序遇到错误',e) //捕获特定异常
else: //未遭遇异常时
finally: //必须要释放的内容e.g.文件
手动抛出异常:
raise AttributeError('属性错误')
简单的代码测试
import unittest
def get_formatted_name(first,last)
full_name = "{} {}".format(first,last)
return dull_name.title()
print(get_formatted_name)('Tom','Lee')
测试文件:
import unittest
from main import get_formatted_name
class NameTestCase (unittest.TestCase):
def test_title_name (self):
formatted_name = get_formatted_name('tom','lee')
self.assertEqual(formatted_name,"Tom Lee")
if __name__ =='__main__':
unittest.main()
测试文件中:
def setUp(self):
self.c = Coder('Tom')
self.c.skills = ['Python','.NET']
多态
import math
class Circle:
def __init__(self,radius):
self.radius = radius
@property
def area(self):
return math.pi*self.radius **2
def get_area(self):
return math.pi * self.radius **2
c = Circle(4.0)
print("圆的面积是:{}".format(c.get_area()))
print("圆的面积是:{}".format(c.area))
class Employee:
def __init__(self,department,name,birthdate,salary):
self.department = department
self.name = name
self.birthdate = birthdate
self.salary = salary
def give_raise(self,percent,bonus = .0)
self.salary = self.salary *(1+ percent) + bonus
def __repr__(self):
return'<员工:{}>'.format(self.name)
def working(self):
print('员工:{},在工作...'.format(self.name))
class Programmer(Employee):
def__init__(self,department,name,birthdate,salary,specialty,project):
super().__init__(department,name,birthdate,salary)
(或Employee.__init__(self,department,name,birthdate,salary))
self.specialty = specialty
self.project = project
def working (self):
print('程序员:{}在开发项目:{}...'.format(self.name,self.project))
if __name__=='__main__':
p = Programmer('技术部',‘Peter’,datetime.date(1990,3,3),8000,'Flask','CRM')
多态:属于同一类型的不同实例,对同一消息做出不同响应
class Department:
def__init__(self, department,phone,manager)
self.department = department
self.phone = phone
self.manager = manager
class Employee:
def__init__(self, department: Department,name)
self.department = department
self.name = name
if __name__ =='__main__':
dep = Department ('技术部','010-87718391','张三')
p = Programmer(dep,'Peeter')
print (p.department)
面向对象的特征:
封装
继承 提高代码重用
多态
class Book:
def __init__(self,title,price,author): //赋默认值的参数需在最后
self.title = title
self.price = price
self.author = author
if __name__=='__main__':
book = Book('Python经典',price=29.0,author='Tom')
实体化后调用时显示有意义信息的方法:
def __repr__(self):
return '<图书:{} at ox{}>'.format(self.title,id(self))
打印时:(若不用该函数,则与__repr__(self)代替)
def __str__(self):
return'[图书:{},定价:{}]'.format(self.title, self.price)
统计图书的个数 -- 全局 -- 和实例无关的东西不要写到init中,不加self
class Book:
count = 0
def __init__(self,title,price,author): //赋默认值的参数需在最后
self.title = title
self.price = price
self.author = author
Book.count+=1
def__del__(self):
Book.count -=1
//未绑定方法
def cls_method (cls):
priny(‘类函数’)
@staticmethod (//若加上可以通过实例调用,最好不要加)
def static_method():
print('静态函数,逻辑上与实例无关')
if __name__=='__main__':
book = Book('Python经典',price=29.0,author='Tom')
del(book3)
print('图书数量:{}.format(Book.count)') //此处count也可以通过实例名调用:book.count,但不建议,可自己改掉
Book.cls_method(book)
Book.static_method()
import datetime
class Student:
def__init__(self,name,birthdate):
self.name = name
self.birthdate = birthdate
方法1:
@property //属性,装饰器
def age(self):
return datetime.date.today().year - self.birthdate.year
@age.setter
def age(self,value):
raise AttributeError('禁止赋值年龄!')
@age.deleter
def age(self):
raise AttributeError('禁止删除年龄!')
方法2:定义函数
def get_age(self):
return datetime.date.today().year - self.birthdate.year
if __name__=='__main__':
s = Student('Tom', datetime.date (1992.3.1))
print(s.birthdate)
print(s.get_age( ))
print(s.age)
引入模块
import
import model
if __name =="__main__"
print(model.page)
from
from models from page
if __name =="__main__"
print( page)
from models import *
if __name =="__main__"
print( page)
取别名
import models.test as ...
from models import test ad m_test
使用模块的原因:
1.代码重用
2.命名空间
3.实现数据或服务共享
步骤:
1.找到模块文件
2.编译为字节码
3.运行模块文件
搜索范围:
1.当前程序主目录
2.环境变量目录下
3.标准库
4.扩展库import importlib、
重新载入(reload之前要importlib模块):
import importlib
importlib.reload(models)
错误写法:
from models import test
reload(models)
因为reload只认识模块,不认识from
按目录组织
directory只能从文件管理来管理文件
若要成为文件路径的一个部分 -- 包 -- python package
__init__.py只在当前包第一次被调用的时候执行
用途:第三方的库,包的导入
3.3以下改文件必须要,3.3以上可省略
面向过程:c(最贴合硬件,底层开发) -- 数据结构和算法
面向对象:抛开代码,以符合人的思维习惯分析解决问题,对象的特征和行为
面向对象
图书管理系统
面向过程的三个特性:
封装(提高代码重用,降低代码冗余)
def search_book(title)
print('搜索包含关键字{}的图书'.format(title))
book = {'title': 'python 入门', 'price':39.00,'author':search_book}
print(book.get('price',0.0))
book.get('search_book')('python')
步骤:
1.面向对象分析:OOA
2.类定义对象代码模板(蓝图)uml关系类图(把分析对象编程代码)OOD
3.实例化(创建内存对象)OOP
实现:
1.分析对象的特征和行为
2.写类描述对象模板
3.实例化,模拟过程
继承 多态
代码:
import datetime
class Book: //类名大写字母开头
def __init__(self,title,price=0.0,author=' ',publisher= None,pubdate=datetime.date.today()): //初始化器
self.title = title
self.price = price
self.author = author
self.publisher = publisher
self.pubdate = pubdate
def __repr__(self):
return '<图书{}>'.format (self.title)
def print_info(self):
print('当前这本书的信息如下:')
print('标题:{}'. format(self.title))
print('定价:{}'. format(self.price))
print('作者:{}'. format(self.author))
print('出版社:{}'. format(self.publisher))
print('出版时间:{}'. format(self.pubdate))
book1 = Book('c#经典', 29.9,'Tom','优品课堂',date(2016,3,1)) //实例化
book2 = Book('入门到精通')
book2.author='优品'
book1.print_info()
动态类型
函数的参数匹配
def func(a,b,c)
print(a,b,c)
fun(1,2,3)//默认位置匹配
fun(c=1,b=2,a=3)//名称匹配
默认一些值时:
def func(a,b=2,c=3)
print(a,b,c) //调用时可省略传值
func('a','b','c')
重载
或使用tuple来传递参数,但一定要传至少一个
def avg(score,*scores)
//或 def avg(*scores)
return sum(scores)/len(scores)
不能直接传一个定义好的tuple
//错误情况:
score = (89,90,91)
result = avg(score)
//正确情况
score = (89,90,91)
result = avg(*score)
//直接传字典表
def display(**employee)
print(employee)
display(name=‘tom’,age=22)
字典表的两种声明方法
或
emp=dict(name=‘tom’,age=22)
def display(**employee)
print(employee)
display(**emp)
*args 任意量参数
**kwargs 任意量关键字参数
lambda表达式 -- 定义匿名函数
f = lambda name: print(name)
f('tom')
f2 = lambda x,y: x+y
print(f2(5,3))
def hello_chi(name):
print('您好',name)
def hello_eng(name):
print('hello',name)
while True:
name=input(‘请输入姓名:\n’)
if name = ‘stop’:
break
language = input(‘请选择语言:\n c:中文版\n, e:英文版\n j:日文版')
if language language =='c':
hello.chinese(name)
elif language =='e':
hello_english(name)
elif language =='j':
(lambda name:print('...',name))(name)
if language language =='c':
action = hello.chinese
elif language =='e':
action = hello_english(name)
elif language =='j':
action = lambda name:print('...',name)(name)
action(name)
字典表可以给方法
def hello_chinese(name):
print('你好:',name)
def hello_english(name):
print('hello:',name)
operation={
'e': hello_english,
'c': lambda name : print ('你好', name)
}
while True:
name = input('请输入姓名:\n')
if name == 'stop':
break
language = input ('请选择语言版本:\n' c: 中文版\n e:英文版\n)
operation. get(language, hello_chinese)(name)
def hello_chinese(name):
print('你好:',name)
def hello_english(name):
print('hello:',name)
def hello(action,name):
action(name)
hello(hello_chinese,'Tom')
hello(lambda name: print('...',name), 'Tom')
l = list(range(1,21))
result = []
//1. 使用循环,效率最低
for n in l:
if n % 2 ==0
rasult.append(n)
//2.使用推导
result = [x for x in l if x%2 == 0]
// 高级工具:map(),返回结果为map类型
def add_num(x):
return x+5
res = list(map(add_num,l) ) //灵活性最高
//若不写list则显示不出来列表
res = list(map(lambda n: n**2,l)
print(result)
filter(函数,可迭代对象)
l = list (range(1,11))
def even_num(x):
return x%2 ==0
res = list(filter(even_number,1))
print(res)
或: res = filter (even_num,1)
for n in res:
print(n,end='')
或:
res =filter(lambda n: n%2 ==0, 1)
推导最好
函数 function
定义代码目的:最大化代码重复&最小化代码冗余&过程分解
def 函数名():
形参
实参
从外往里传
从里往外传:返回一个值
函数变量的作用域local(区分global)
形参的生命周期在函数体内(本地)
x=55
def func():
x=99
print(x)
x=55
def func():
global x
x=99
print(x)
built-in(作用域比global还要高)
封装(函数套函数时用到)
def func():
x=100
def nested():
x=99
print(x)
print (x)
//nested没调用,所以没有print
def func():
x=100
def nested():
x=99
print(x)
nested()
print (x)
外层x成为封装--enclosure (local之上global之下)
用外侧封装的生命
def nested():
nonlocal x
定义新函数会覆盖原来的内置函数
参数:
def change_num(x)
x+=10
x=5
print('x={}'.format(x)) //5
change_number(x)
print('x={}'.format(x)) //5
整型这一数据类型不能改变
由于这一特性,在函数调用x时x传的值为副本,即x一直不改变
函数的传递时,不可变类型(int float tuple str)传递副本给函数,函数内操作不影响原始值
可变类型(列表,字典表),传递地址引用,函数内操作可能会影响原始值
change_list(l[:])
change_list(l.copy())
迭代(iterate)
可直接遍历的类型:list, tuple, dictionary, file
可迭代的对象(实现迭代器协议的对象)支持遍历/循环 -- 目的:节省内存
可实现迭代协议的对象:对象内部有next方法:__next__()
f.__next__()
全局方法:next(f)
file 有__next__
list没有
但为啥还能for,因为for实现了额外步骤
可迭代的对象
字典表遍历时只能遍历取出键
d={'a':1,'b':2}
for k in d:
print{k}
如下写法错误:
d={'a':1,'b':2}
for k,v in d:
print{k,v}
迭代工具
for
推导
map
迭代器对象&可迭代对象
迭代器对象对象已经实现
可迭代对象需要额外加iter()方法,用于生成迭代器,用for时自动生成 __iter__()
iter(f) is f
True 则说明是迭代器对象
若需要可迭代对象能使用__next__()函数,可以用:i = iter(urls) 当urls为列表时
为什么列表不实现:因为列表可嵌套列表,可能使结构复杂
内置可迭代对象
(1)range() 类型为range
zip //负责将两个集合合成一个
result = zip (['x'],[1])
类型为zip
print结果为元组
有next方法
map将每一个元素应用函数的执行
while循环
while true: (死循环)
x = 'youpinketang'
while x:
print (x, end = '')
x=x[1: ]
break
从循环中跳出
continue
跳到循环头部进行下一次循环
while x:
x-=1
if x%2 !=0:
continue
print(x,end='')
while True:
name = imput('请输入您的姓名:')
if name =='stop'
break
age = imput('请输入您的年龄:')
print('您好:{},您的年龄是:{},欢迎学习'。format(name,age))
pass
占位符,对代码的不确定
else
for 循环:
found = False
for x in range (1,5)
if x ==6:
found = True
print('已经找到了',x)
break
if not found:
print ('没找到')
for x in range(1,5):
if x ==6:
print('有这个数字',x)
break
else:
print('没找到')
for x in [1,2,3,4]:
print (x, end =' ')
sum = 0
for x in [1,2,3,4,5]
sum+=x
print(s um)
只遍历字典表的键
for key in emp:
print('{} =>{}'.format (key, emp.get(key,'未找到')))
or
for key in emp.keys():
print(key)
只遍历值
for key in emp.values():
print(key)
values不是列表,是可使用for,while循环的可迭代的试图结构,为了减少对内存的占用
找交集
result =[]
for x in s1:
if x in s2:
result.append(x)
print (result)
l = [x for x in s1 if x in s2]
print(l)
range()
for x in range (1,101,2)
enumerate():可获得现在在循环的是第几项
s='youpinketang'
for idx, item in enumerate(s):
print('{}){}'.format(idx,item))
语句,表达式,流程控制
1. 代码风格
(1)代码格式指南-PEP8
(2)缩进4空格
(3)一行不超过79字符
(4)等于号前后空格
(5)空行,逻辑分割的隔两行
2.语句
(1)赋值语句
x=5
通过元组赋值:(x,y) = (5,10)
x,y=5,10
序列声明变量可以接受任意类型
序列赋值:
[a,b,c]=(1,2,3) 左右数量对应时不会出错
a,b,c='uke'
多了:
若序列赋值左右数量不一致时会报错,避免方法:列表的切割:
方法1
s='youpin'
a,b,c=s[0],s[1],s[2:]
方法2
a,b,*c=s
扩展序列解包赋值(c后的为序列)
a,*b,c=s
不够:
后面多出来的是空列表
ps:只能有一个星号
多目标赋值
a=b=c='uke'
(2)a = b =[]
a.append(3)
//b也相应变成[3]
分开方法:
a=[]
b=[]
a.append(3)
分开方法2
a,b=[],[]
参数化赋值
+=
列表的参数化赋值
l=[1,2]
l+=[9,10]
加元素 append
加列表extend (和+=比效率更高)
表达式
(1)函数调用
(2)方法调用
(3)字面值
(4)打印操作
打印两个:
url = 'www.codeclass.com'
s='123'
print(url,s,sep='|' )
print(s,url,end='...\n')
将信息打印到文件:
print (s,url,end='...\n',file=open('result.txt','w',encoding='utf8'))
流程控制
(1)if语句
score = 75
if score >=90:
print ('优秀')
elif socre >=80
print('良')
elif score >=60
print('及格')
else print('不及格')
多重分支
def add(x):
print (x+10)
operation = {
'add':add,
'update': lambda x: print(x*2)}
}
def default_method(x):
print('无处理')
operation.get('delete',default_method)(10)
三元表达式
if score >=60
result='及格'
else
result = '不及格'
等价于
result = '及格' if score>=60 else score<60
文件与类型汇总
1. 基本语法:file = open('文件名',mode)
写文件:myfile=open('hello.txt','w')
myfile.write('优品课堂\n')
myfile.close()
读取文件:f=open('hello.txt','r')('r'可省略)
f.read() --读取所有内容
read相当于指针
重新打开: f = open('hello.txt')
f.readline()
f.readline()
放入列表:
l = open ('hello.txt').readlines() (类型为列表)
for line in l
print(line)
为了防止乱码可指定编码:
f = open ('course.txt','w',encoding='utf8')
读取二进制文件:rb
2. mode: r(读) w(写)a(追加) b(二进制文件)+(读+写)
3.类型的丢失
x,y,z=1,2,3
l=[1,2,3]
f=open('datafile.txt','w')
f.write('{},{},{}'.format(x,y,z))
f.write(str(l))
f.close()
chars = open('datafile.txt').read()
序列化--pickle存取python对象:
d ={'a':1,'b':2}
f = open('datafile.pkl','wb')
import pickle
pickle.dump(d,f)
f.close()
不要用记事本打开
open('datafile.pkl','rb').read() (读取无意义)
f = open ('datafile.pkl','rb')
data=pickle.load(f)
data['a']
data.get('b')
防止忘记关闭文件的做法:
传统方法:
f=open('course.txt')
l=f.readlines()
for line in l
print(line)
close()
新方法
with open('course.txt') as f
for line in f.readlines()
print(line)
数据类型汇总:
集合
1.序列 可变(列表list)/不可变(字符串string,元组tuple,字节数组)
2.映射 字典表dict
3.集合 set:集合信息不能有重复,花括号,但没有键
数字
1.整型 int/boolean
2.浮点型 float/decimal/fraction
可调用
1.函数 function
2.生成器 Generation
3.类 Class
4.方法
其他
1.模块
2.实例
3.文件
4.None
5.视图
内部
1.type
在内存中的表现:
l=['abc',[(1,2),([3],4)],5]
字典表 dict (映射类型)
通过键值对存储索引
1.定义代码
(1)通过字面值d={'ISBN':'223421','Title':'python入门','price':39.00}
(2)通过dict构造函数声明
emp = dict (name='Mike', age=20,job='dev')
呈现的顺序不是输入顺序,乱序(根据键哈希以后产生的结果)
2.通过方括号下标索引来找
3.插入一个值
d['author']='Jerry'
4.与列表的区别:列表不能访问不存在的索引
6.检索某一键值(防止抛异常)
d.get('price')
7.用get设置默认值防止抛异常
d.get('price',0.0)
8.字典表长度
len(emp)
9. 字典表可以原位改变
d['Price']=99.00
10.字典表的合并
dep = {'department':'技术部'}
emp.update(dep)
11.弹出某一项
emp.pop('age')
12.只关注键
dict.keys() --返回视图
13.只关注值
dict.values()
for k in emp.keys():
print(k) //像列表一样遍历
14. emp.items()
形式变换:
for k,v in emp.items():
print('{}=>{}'.format(k,v))
14.列表不能作为键,只能是不支持原位改变的作为键
15.支持嵌套
emp = {'age':20,'name':{'firstname':'Jerry','lastname':'Lee'}}
取出:
emp.get('name')
emp['name']['firstname']
16.排序
方法1:
ks = list(d.keys())
ks.sort()
for k in ks:
print(d.get(k))
方法2(全局函数):
ks=d.keys()
for k in sorted(ks):
print(k,d.get(k))
元组tuple
1.与列表类似,但不支持原位改变,圆括号声明。
2.是任意对象的有序集合,通过下标访问,属“不可变”类型,长度固定,任意类型,任意嵌套
3.元组的声明
(1,2)
(1,2)+(3,4)
1,2
单个元素声明元组(逗号用来标识类型):
x=(40,)
求长度:len(x)
x
4.通过元组的特性便于交换变量
5.支持推导
方法1:
for x in t:
print(x**2)
方法2(放入列表中):
(1) res = []
for x in t:
res.append(x**2)
(2) res = [x**2 for x in t]
6.检索元素位置
t.index(3)
7.统计元素次数
t.count(3)
8.namedtuple
from collections import namedtuple
Employee = namedtuple ('Employee', ['name','age','department','salary'])
Jerry= Emloyee('Jerry',age=30,department='财务部',salary=9000.0)
Jerry.name
布尔型和列表
1. python中的布尔型介于true/false和int型之间,本质相当于int的0,1
2. 列表支持原位改变
l=list(s)
s=''.join(l)
3. 字符串分割
url.split(',')---分割成列表
l=url.split(',')
4. function -- 函数
s.split() -- 方法
5. .startswith, .emdwith, .find(返回位置)
6. 格式化字符串
'{0} => {1}'.format (a,b)
7. upper
列表 list
1. 与数组相似,但类型可以不一致,是任意对象的有序集合,可以通过索引下表访问元素,长度可变,属可变序列(可原位改变)。
2. 基本操作
len([1,2,3])
相加
将字符串的字符变为元素 list
取出:遍历
判断是否在列表中:遍历 or in
'k' in l
for c in l:
print(c, end='|')
(tab和空格不要混合使用)
运算:
l= [1,2,3,6,9]
res=[]
for i in l:
res.append(i**2)
列表的 推导:
l1=[i**2 for i in l]
[]*3
追加 .append 追加一个元素
扩展 .extend 扩展一个列表
内置排序算法:l.sort(); l.reverse()
l.pop() -- 类似于堆栈的操作
删除元素:del (l[0])(全局函数)
找出元素位置l.index(7)
数元素个数l.count(7)
修改列表时是否影响其他列表(是引用类型,支持原位改变的问题)
l2=l1 影响
拷贝副本(不影响)
l3=l1.copy() 不影响
l4=l1[:] 不影响
数值与字符串
1. 数值类型
1.1 变量要先声明再使用,声明需至少赋一次值
print (age)
Traceback (most recent call last):
File "D:\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3296, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-2-dbcadc9b8512>", line 1, in <module>
print (age)
age = 20
print (age)
20
1.2 浮点型精度问题--计算机硬件存储结构描述浮点型的特性造成--可用decimal解决
1.1+2.2
Out[5]: 3.3000000000000003
1.3 数值显示的格式化(保留小数位数)
(1)仅在界面上显示情况发生变化:通过字符串
f=3.33333
'f={0:.2f}'.format(f)
1.4 比较,返回结果为布尔型
1.5 相除
10/4
10//4
10//4.0
向左
import math
math.floor(3.4)
向0
math.trunc(3.94)
四舍五入
round
1.6 python的整型大小只受限于内存大小和计算机配置
八进制:0o开头
十六进制:0x开头
二进制:0b
转换:oct(八进制)hex(十六进制)bin(二进制)
1.7 decimal
import decimal
decimal.Decimal('3.14')
2. 字符串
2.1 声明
2.1.1 直接声明 '', ""
2.1.2 定义说明文档 """ """ 不会被忽略,可生成文档
2.1.3 转义符 --地址:path='C:\\abc\\xyz.txt'
忽略转义符:path = r 'c:\abc\xyz.txt'
\
\n 换行
\b 退格
\t Tab
\a 响铃
2.1.4 字符串基本操作
(1)len
(2)s = 'hello'
for c in s
print (c, end=' ')
(3) 选取
s[0]
s[0:4]
s[-1]
s[len(s)-1]
s[:]
s[::2]
s[::-1]
(4) 字符串和整型不能相加
(5)字符和asc码的对应关系
ord
chr
(6)不支持原位改变
若改变则用:
h.replace('e','a')
h=h.replace('e','a')
1、windows命令提示符
切换盘
进入目录:cd
返回上级目录:cd..
返回根目录cd\
列出目录:dir
2、 代码(.py)--解释器--字节码(.pyc)--PVM托管运行-- 机器码
3 、变量表 对象 类型约束
动态类型