张鑫 18511446896
--------------------------------------------------------------------------------------
Day1
1、概述
2、环境搭建、工具安装与配置
3、Python的运行原理
4、基本知识:缩进与行、跨行、注释
5、字符集编码问题
6、变量与数据类型
7、Python的内存管理机制(指针存储、动态类型、可变与不可变、引用计数)
8、Python的内置数据类型
9、Python的运算符(算数、比较、赋值、逻辑、成员、三目)
10、字符串常用属性与操作
---------------------------------------------------------------------------------------
Day2
11、输入与输出
12、控制语句之分支语句
13、控制语句之循环语句
14、元组
---------------------------------------------------------------------------------------
Day3
15、列表
16、字典
17、函数
18、类和对象
---------------------------------------------------------------------------------------
Day4
19、异常
20、模块
21、常用标准库
22、Python多线程
23、装饰器(权重)
24、上下文协议、文件读写
25、数据库操作
26、web相关
------------------------------------------1、概述--------------------------------------------
新的性能课程体系,前4天 Python语言基础
原因:
1. 性能测试工具选型——Locust
--开源(Python)、支持二次开发、易于平台化
--基于协程,节省资源开销,支持高并发
--HTML+JS界面,整洁、跨平台、易扩展
--使用Python语言编写脚本
2. 企业、社会对测试代码能力的要求提升
--更好地应对笔试、面试
--突破职场瓶颈、拓宽发展空间
3. Python的应用越来越广泛
--自动化测试、大数据、人工智能
--语法相对简单、易上手
--自带标准库、扩展库非常多 Battery included
--可以方便地操作其他程序,引入其他语言写成的库
学习的侧重点有哪些?
测试用到的知识点
Python基础语法和知识点
Python常用模块、常用的第三方库
学习方法:
讲过的内容,认真练习(抄写、调试、自己写)
做好作业,按时提交
多练习
100天 每天100行
原则:
不追求难,只追求通用、实用
测试中用不到的难点,可以后续工作中自己寻求新的突破
--------------------------------------2、环境搭建与配置-------------------------------------------
一、安装Python-解释器和虚拟机
*目前常用的有Python2.X和Python3.X
Python3.X相对之前版本是一次较大的升级,
Python3.X在设计时没有考虑向下兼容。
python3 和 python2 有一些差异。
两个版本目前都在维护,可以选用。
*选择哪个版本进行学习?Python3
从Python2切换到Python3,难度并不大:
官方迁移指南提供了在Python 3中运行Python 2代码的建议
区别:http://www.runoob.com/python/python-2x-3x.html
Windows:
下载地址:https://www.python.org/downloads/windows/
Linux(下载源码进行安装)
下载地址:https://www.python.org/downloads/source/
Mac OS X
下载地址:https://www.python.org/downloads/mac-osx/
二、PATH环境变量配置
环境变量作用
设置方法
三、Python编辑器安装
1.cmd下执行python 交互式解释器模式
2.安装python自带的编辑器IDLE
3.专业的编辑器 Pycharm 优点:
人性化设计:代码联想与提示等
PyCharm安装与破解
配置:
主题、字体、字号设置
------------------------------------------3、Python的运行原理-------------------------------------------
编写第一个程序
创建Python项目,“Pure Python”
改名
*Python虚拟环境
项目下创建python文件
创建项目的默认路径
文件:day1.py
内容:最简单
运行方法:
1、Pycharm直接运行
2、cmd命令行执行
***练习:
自己创建一个项目,创建一个简单的python文件,两种方式(Pycharm、cmd命令行)执行
运行原理:
Python、Java-先编译、后解释-虚拟机(图)
.pyc演示 day1.py demo.py
手动编译(了解):
目的:执行效率更高,看不到原始代码,暂时保密
python -m py_compile filepath
python -m compileall dirpath
------------------------------------------4、一些Python的基本知识-------------------------------------------
1、缩进
大部分语言用{}标识代码块,嵌套很深时,大括号层数很多
为了清晰,需要通过缩进来帮助查看
Python
强制缩进
习惯:每一层级,固定缩进4个字符(空格)
要求:
1、使用固定的编辑器
2、采用4个空格进行缩进
对于PyCharm,默认配置——一个Tab符相当于4个空格
其他编辑器不可以用Tab符
错误举例,使用notepad++编辑,
def mytest():
if True:
print('a')
else:
print('b') #以上缩进都是使用制表符
print('c') #此行采用空格缩进
mytest()
以下使用pycharm编辑,自动缩进和tab都会被处理成四个一组的空格
def mytest2():
if True:
print('a')
else:
print('b') 自动缩进
print('c') 两个tab
print('d') 8个空格
2、换行显示
字符串\
表达式\
定义的列表、元组,等
python中不需要以分号作为语句结束,正常换行自动结束
3、定义多行字符串
xml举例-天气webservice接口
4、注释
作用:(1)代码功能说明
(2)保留代码,但暂不执行
单行注释
多行注释(区域注释)
批量注释
特殊注释
#! /usr/bin/python
Linux下指定运行脚本文件时使用的解释器,Windows不需要
5、单引号、双引号
6、字符集编码
计算机存储、处理数据的方式
ASCII:
最早只有127个字母被编码到计算机里,也就是大小写英文字母、数字和一些符号
1个字节
A的编码是65,a的编码是97,小写字母z的编码是122
GBXXXX:
处理中文
2个字节--65535
原本ASCII有的字符
7000多个简体汉字
数学符号、罗马希腊的字母、日文的假名
GB2312---GBK(扩展)
Unicode
把所有语言都统一到一套编码里
unicode是一种编码标准,
具体的实现方法可能是utf-8,utf-16,gbk ……
2字节表示一个字符 UTF-16
4字节表示一个字符 UTF-32
UTF-8
可变长编码
UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节
常用的英文字母被编码成1个字节,汉字通常是3个字节
------------------------------------------5、变量与数据类型-------------------------------------------
数据类型
为了规定数据的存储方式,包括分配内存和磁盘空间,限制存储内容
数据分为 变量 和 常量
变量
变量:占用一部分内存空间,用来存放变量的值(或地址)。用一个标识符(identifier)来表示
a
number ID
class_16_name1
字母 数字 下划线 以字母或下划线开头
区分大小写
number
Number
变量的赋值
=
变量名=变量值
变量名=其他变量名
变量名=表达式
变量名=函数(返回值)
a = 1
print(a)
a = 1
a = a + 1
print(a)
if a == 1:
print('ok')
a = 1
b = a
print(b)
a = 1
b = 2
c = a + b * 2
print(b)
C和Java的变量
使用前先定义,定义时指定变量的数据类型
强制数据类型
int a;
....
a = 2;
a = 3;
a = 'haha'; #会报错
Python的变量
(1)不用预先定义,首次赋值时即实现定义
(2)赋值可以使用任意类型的数据
(3)一个变量的类型不固定
(4)变量值有固定的类型
查看数据类型
type(变量名)
a = 1
print(type(a))
a = 1.2
print(type(a))
a = 'haha'
print(type(a))
为什么会有这样的区别呢?
内存管理机制 Java、C
Python
通过id(变量名)可以查看变量指向的内存地址
*函数简介
数值型
int 整数 实际为长整型,动态长度,最小24字节
float 浮点数 24字节
类型转换
自动类型转换
float>int
+ - *运算时,若类型 不一致,会转换成float型进行运算
强制类型转换
int(X)转换X到一个普通整数
float(X)转换X到浮点数字
chr(X) 将一个整数转换为可对应ASCII的字符
ord(X) 将一个字符转换为对应的ASCII码数值
布尔型
True、False--注意大小写
字符串
'''
ABC
I'm OK
Mary said, "I'm OK"
'''
转义字符:
作用:
1.去掉某些特殊字符的特殊含义,而使用其作为一个普通字符
字符串中的单、双引号、反斜线
2.反斜线与一些字母连用,为了表示一些特殊含义
'''
\n 换行
\r 退回到行首,后续输入会覆盖前面的输入
\t 制表符
\\ 代表一个反斜线字符
'''
r的应用
字符串前加r,代表忽略内部的转义字符
***练习:分别输出以下内容
'''
1. 用换行符和多行注释分别输出
Bob said
I'm OK.
2. div[@id='goodItem']/a
3. Bob said "I'm OK".
4. "C:\Program Files\fnord\foo\bar\baz\frozz"
5. ^test/\d{n,}/$
'''
str(x)将对象 x 转换为字符串
元组(Tuple)、列表、字典
空值 None
None有自己的数据类型NoneType
None表示一个空对象
不是0、False、空字符串
如果函数无return,则默认返回None
** 了解:可变数据类型与不可变数据类型
不可变类型:内存中的那块内容的值不可以被改变。
数字、字符串、布尔值、元组
可变类型:内存中的那块内容的值是可以改变的。
列表(List)
字典(Dictionary)
其它对象
(1)当企图通过+=、append等修改该内存地址内容时,可变类型不会创建出新对象,只在原来地址上对值进行修改。
(2)无论是可变还是不可变类型,对一个变量重新赋值都会创建出新对象;
a = (1, 2, 3)
print(id(a))
a += (4,)
print(id(a))
a = [1, 2, 3]
print(id(a))
a += [4,]
print(id(a))
------------------------------------------6、运算符-------------------------------------------
算术运算符
+
-
*
/ 结果的类型为float
9/2 4.5
** 幂
2**3
% 取余
// floor除
不管操作数为何种数值类型,总是会舍去小数部分,返回数字序列中 比真正的商小的 最接近的 整数数值,
数值类型取决于操作数的类型。
练习:
请写出以下程序的运行结果
a = 21
b = 10
print(a / b) #2.1
print(a % b) #1
a = 11
b = 3
print(a//b) 3
print(a//float(b)) 3.0
a = -11.0
b = 3
print(a//b) -4.0
比较(关系)运算符
返回值为布尔值
不仅可以比较数值,还可以比较其他类型,字符串、布尔值
== 等于 - 比较对象的值是否相等
!= 不等于
>
<
>=
<=
is 两个引用(变量)所指的对象是否相同
a is b
id(a) == id(b)
*数值、字符串、布尔值
定义多个变量,若它们值相等,则这些变量是指向同一对象
a = 'True'
b = 'True'
id(a) == id(b)
a is b
*元组、列表、字典
定义多个变量,若通过直接赋值方式使它们值相等,指向的不是同一对象;
若通过传递的方式赋值,可以使它们指向同一对象。
(对于列表、字典)此时如果对一个变量的值进行了修改,则其他变量的值也会发生变化。
*作业:
请写出以下程序的运行结果
a = 1
b = 1
print(id(a) == id(b)) #True
print(a is b) #True
a = 2
print(id(a) == id(b)) #False
print(a is b) #False
c = "very good morning"
d = "very good morning"
print(id(c) == id(d)) #True
c = True
d = True
print(c is d) #True
e = [1, 2, 3]
f = [1, 2, 3]
print(id(e) == id(f)) #False
print(e == f) #True
print(e is f) #False
g = [4, 5, 6]
id1 = id(g)
g.append(7)
id2 = id(g)
print(id1 == id2) #True
赋值运算符
=
+=
-=
*=
/=
%=
**=
//=
连续赋值
a=b=c=1
a,b,c=1,2,3
值互换
a,b=b,a
逻辑运算符
and 与 两真结果真, 一真一假结果为假,两假结果假
or 或 两真结果真, 一真一假结果为真,两假结果假
not 非
结果: True False
表达式:任意表达式
无论结果是否布尔型
在作为逻辑运算符的操作数时,
'0、空字符串、空列表、空元组、空字典、None'被作为False处理,其他作为True处理。
注意:短路逻辑
and 多个表达式都成立(为True),结果才成立;只要有一个不成立,结果就不成立,后面的不再计算
or 多个表达式中只要有一个成立(为True),结果就成立,后面的不再计算
1 and 2 and 3 and 4
1 or 2 or 3 or 4
***练习:写出下面程序的执行结果
(1)
def a():
print('A')
return 0
def b():
print('B')
def c():
print('C')
return []
def d():
print('D')
return False
if a() or b() or c() or d():
print('ok')
(2)
def a():
print('A')
return 0
def b():
print('B')
def c():
print('C')
return []
def d():
print('D')
return False
if a() and b() and c() and d():
print('ok')
成员运算符
in 如果在指定的序列中找到一个变量的值,则返回true,否则返回false
序列:有序的队列 字符串 元组 列表
not in 如果在指定序列中找不到变量的值,则返回true,否则返回false
应用:查看字符串中是否含有某个值
print('e' in 'hello')
print('ll' in 'world')
身份运算符
也属于比较的一种,结果是布尔值(见前述内容)
is
is not
三目运算符
为真时的结果 if 判定条件 else 为假时的结果
1 if 5>3 else 0
++ 和 --
Python不支持
------------------------------------------7、字符串常用属性与操作-------------------------------------------
字符串的定义、赋值
单引号、双引号、混用:可以在一定程度上避免使用转义字符
长字符串--当字符串跨行
格式化输出
"您账户xxxx于xx月xx日入账工资,人民币xxxxx.xx,xxxxxxxxxxxxxxxxxxx"之类的短信,
xxx的内容都是根据变量变化的
通过%?格式化输出:
在Python中,采用的格式化方式和C语言是一致的,用%实现
在字符串内部,%?代表此处的内容需要被变量填充
数据类型不同
%s 字符串
如果字符串中有% 改用%%
%d 整数
%f 浮点数
格式化整数和浮点数还可以指定整数与小数的位数 '%.2f'
%x 十六进制整数
如果你不太确定应该用什么,%s永远起作用,它会把任何数据类型转换为字符串
在字符串外部,有几个%?占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?,括号可以省略
通过字符串的format()函数格式化输出:
format
str.format(text)
str中包含占位符,text中是要填充的内容
使用'{name}'形式的占位符
使用'{}'占位符
使用'{0}','{1}'形式的占位符
***作业:
1.练习:格式化输出以下字符串:
'亲爱的小岳岳你好!你9月的话费是32.00元,余额是18.00元'
其中姓名、月份、话费、余额为可变的值。
用%?占位符和format()两种方法实现。
***作业:
1.输出一个get请求地址,形如:
http://192.168.2.111/huice/event/api/add?title=python大会&time=2018-01-06
其中可变的内容为:
协议类型:形如http
主机名:形如192.168.2.111
地址:形如huice/event/api/add
参数:形如title=python大会&time=2018-01-06
常用属性和操作
长度
内置方法len(string)
序列
在Python中,最基本的数据结构是序列 -- 有序的队列
序列中的每个元素被分配一个序号——即元素的位置,也称为索引
第一个索引是 0,第二个则是 1,以此类推
若长度为n,则最后一个元素的索引为n-1
序列中的最后一个元素标记为 -1,倒数第二个元素为 -2
常用的内建序列:
列表、元组、字符串
“字符串其实就是一个字符元素组成的序列”
索引和分片(切片)
索引:string[index]
超出索引:IndexError: string index out of range
*遍历字符串中的每个字符
0到 len-1
*翻转输出每个字符
-1 到 -len
分片(截取)
格式:string[头下标:尾下标:步长]
步长默认为1
头下标为空:从第一个字符开始截取
尾下标为空:截取到最后
[:]字符串“拷贝”
越界不会报错,取到结尾
字符串翻转
[::-1]
***********10.27***********
作业讲解(9:30-9:45)
字符串连接(9:45-10:00)
+
1.可以通过加号进行拼接,但非字符串型需要先强制转成字符串型,使用str()函数转换
2.每连接一次,就要重新开辟空间,然后把字符串连接起来,再放入新的空间
大量字符串拼接时,效率低
join
'sep'.join(seq)
上面的语法即:以sep作为分隔符,将序列seq所有的元素合并成一个新的字符串
*加号连接效率低是在连续进行多个字符串连接的时候出现的,如果连接的个数较少,加号连接效率反而比join连接效率高
对于多个元素组成的序列,只有当它们之间使用的分隔符都一样时,才可以用join()
*对象的函数 -> 类和对象介绍(10:00-10:05)
函数 len(), id(), type()
a = 'Hello{name}'
a.format(name='tls')
'&'.join()
=> 类和对象
字符串替换
str.replace(old, new[, max]) 返回新字符串
参数:old -- 将被替换的子字符串。
new -- 新字符串,用于替换old子字符串。未找到就不替换
max -- 可选字符串, 替换不超过 max 次
字符串查找
find
str.find(target, [start,end) )
在字符串中查找指定字符串首次出现的index,找不到时返回-1
index
str.index(target, [start,end) )
在字符串里查找子串第一次出现的位置,找不到子串会抛出异常
**字符串分割
str.split(sep, [,max])
将一个字符串分裂成多个字符串组成的列表
不带参数时以空格进行分割
带参数sep时,以该参数值为分隔符进行分割
未查询到分隔符时,列表只包含原始字符串
字符串大小写
转换:
str.upper() --转大写
str.lower() --转小写
str.capitalize() --首字母大写,其余字母小写
判断:
str.istitle() --是否是每个单词首字母都大写的
str.isupper() --字母是否全是大写
str.islower() --字母是否全是小写
字符串去空格
str.strip() --去掉字符串的左右空格
str.listrip() --去掉字符串的左边空格
str.rstrip() --去掉字符串的右边空格
其他
str.isalnum() --是否全是字母或数字,并至少有一个字符
str.isalpha() --是否全是字母,并至少有一个字符
str.isdigit() --是否全是数字,并至少有一个字符
str.isspace() --是否全是空白字符,并至少有一个字符
str.count(target,[min,max)) --统计某个字符在字符串中出现的次数
str.startswith(target) --判断字符串是否以某个字符串开始
str.endswith(target) --判断字符串是否以某个字符串结尾
------------------------------------------8、输出与输入(10:20-10:35)-------------------------------------------
输出
print()
Python3.x时代,print是一个函数
输出内容
1. 字符串和数值类型
2. 变量--无论什么类型,数值,布尔,列表,字典...都可以直接输出
输出单个数据:
print(1)
print('')
print(a)
print(type())
print([])
print(())
print({})
输出多个数据
print(A, B, C)
*默认以空格分隔;即默认分隔符为' ' 。
如果要以其他字符分隔,需加sep='xxx'参数
*默认输出结束自动换行,即默认结束符为'\n',
如果不需要换行并需要其他结束符,需加end='xxx'参数
*默认输出到控制台
如果需要输出到文件,需加file=参数
st = open('1.txt', 'w')
print(1, 2, 3, file=st)
输入
input
变量名 = input(提示信息)
将所有输入作为字符串看待
例: 接收一个数字,把这个数字加1再输出出来
------------------------------------------9、控制语句-------------------------------------------
分支语句(AB 10:50 - 11:30)
有多种情况需要处理,根据不同的情况,代码执行不同的分支
例子:接收用户输入的一个数,判断能否被3整除
如果用户输入不是纯数字,怎么处理?
如果能被3整除,输出什么?
如果不能被3整除,输出什么?
有没有其他情况?
第一种:
if 条件表达式:
条件表达式为真时,执行此代码块
if判断条件还可以简写,比如:
if x:
print('True')
只要x是非零数值、非空字符串、非空list等,就判断为True,否则为False(None,0,空列表、元组、字典,'',False)
第二种:
if 条件表达式:
条件表达式为真时,执行此代码块
else:
条件表达式为假时,执行此代码块
第三种:
if 条件表达式A:
条件表达式为真时,执行此代码块
elif 条件表达式B:
条件表达式B为真时,执行此代码块
第四种:
if 条件表达式A:
条件表达式为真时,执行此代码块
elif 条件表达式B:
条件表达式B为真时,执行此代码块
elif 条件表达式C:
条件表达式C为真时,执行此代码块
else:
以上表达式都为假时,执行此代码块
注意:1.如果在某个判断上是True,把该判断对应的语句执行后,就忽略掉剩下的elif和else
2.Python中没有switch语句,所以多个条件时,可以用elif来实现
最容易出现的条件靠前写。
复杂 if 条件
可包含 and、or、not,用()标识计算优先级
if 嵌套
if xxx:
xxxxxxxxxxxxxxxxxxxxx
if xxx:
xxx
else:
xxx
else:
xxxxxxxxxxxxxxxxxxxxx
举例:
1.接收用户输入的一个字符串,判断是否为纯数字
2.接收用户输入的一个数,判断能否被3整除
**整体缩进和取消缩进
练习:
1.接受用户输入的一个字符串,如果是正整数, 就判断是否能同时被3和7整除
2.根据输入的月份来输出,这个月有几天(默认2月有28天,不考虑闰年),
要求输出格式:xx月有xx天!
作业:
1.接收用户输入一个年份,判断是否是闰年(判断闰年的方法是该年能被4整除并且不能被100整除,或者是可以被400整除)
2.某电信公司的市内通话费计算标准如下:三分钟内0.2元,
三分钟后每增加一分钟增加0.1元,不足一分钟的按一分
钟计算。要求编写程序,给定一个通话时间(单位:秒)
计算出应收费金额。
3.接收用户输入一组整数,输入负数时结束输入,输出这组数字的和:格式--您输入的数字之和是:10
4.某市的出租车计费标准为:3公里以内10元,3公里以后每0.5公里加收1元;每等待5分钟加收1元;
超过15公里的加收原价的50%为空驶费。要求编写程序,对于任意给定的里程数(单位:公里)和等待时间(单位:秒)
计算出应付车费
循环语句(前两种 11:30-12:00)
循环的必要性:
1、保证程序不退出,一直能响应和处理
例:根据月份判断天数,一直判断下去
2、代替人做重复性工作
最简单例子:打印1-100以内所有的数
判断
处理
while 循环
只要条件满足,就不断循环
while 条件表达式:
条件表达式为真时,执行此代码块
举例:根据输入的月份来输出,这个月有几天(默认2月有28天,不考虑闰年)。不退出,重复执行
练习:(1)重复接受用户输入的一个字符串,如果是正整数, 就判断是否能同时被3和7整除。
使用while循环容易产生死循环
while True:
如果不通过break结束,就是死循环
while 表达式:
当在循环体里没有语句让表达式趋近于不成立,也是死循环
举例:模拟倒计时
for 循环
第一种:for...in 序列(str、list、tuple)
*适用于:序列内容不太多,或容易列出时
for ele in [1,3,7,2,4]:
print(ele)
for c in 'Hello Huice':
print(c)
for c in '大家好':
print(c)
总结:for ele in seq 的理解
举例:1、对于列表[1,5,2,4,9],打印其中每个数的平方
2、对于字符串'Huice',打印出每个字符的ASCII码值(十进制)
练习:
输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数
*循环后对数据的处理
判断
容器、计数器、计算器、其他
第二种:for...in range(start, end, step)
range 范围
*适用于:1、连续整数范围
2、列表、元组内容较多,不易列出————通过索引遍历
3、其他涉及序列索引时
for num in range(1, 101)
for num in range(1, 101, 2)
for num in range(100, 0, -1) 倒序
for idx in range(0, len(seq)):
...seq[idx]...
从0开始且步长为1时可以省略初始值0,只写尾下标:
for idx in range(len(seq)):
...seq[idx]...
例:分别使用while循环和for循环,打印 1-100中所有的数
**总结———— for 循环和 while 循环的区别:
while 循环,while表达式中不包含数据变化 和 结束条件
数据变化要在循环体里写;
结束条件通过数据变化形成(直到while表达式值变为False),或通过一定条件下的break完成。
for 循环自带数据变化和结束条件,不用在循环体中写;
依次循环遍历范围内的每个值,遍历完自动结束。
for 后面的变量不用预先定义,while 表达式里的变量需要预先定义
练习:
1.分别使用while与for循环输出1-100之间的所有偶数
2.用python输出一个简单的旋转风车,模拟等待图标
第三种:for...in enumerate(seq) (至最后 13:30-14:30)
enumerate()函数
适用于:同时用到序列中的 元素 和 元素下标
举例:以下列表中是按照销量高低排序的手机品牌名称
['OPPO', 'vivo', 'Apple', 'Huawei', 'HONOR', 'MI', 'MEIZU']
格式化输出为下面的形式:
第X名:xxxx
第X名:xxxx
... ...
第X名:xxxx
练习:给一个字符串,找出其中数字分别是第几个字符
seq = '2Apples&3Pears&5bananas'
for i, j in enumerate(seq):
if j.isdigit():
print("第%d个字符是数字,为'%s'" % (i+1, j))
break 和 continue
break - 终止循环语句,退出循环
continue - 跳出本次循环,直接进入下次循环
举例:根据输入的月份来输出,这个月有几天(默认2月有28天,不考虑闰年)。不退出,重复执行
循环中的 else
Python特有
代表在循环正常结束后,执行else中的代码块
循环没有执行完,比如break或者return,else中的代码块不执行
占位语句 pass
用于循环体、if代码块、函数体等
暂时或永久,表示什么都不做,只是为了保证程序结构的完整性
嵌套循环、分支/循环互相嵌套
例:
打印一个9*9 的方阵,由星号组成
* * * 第1行
* * * 第2行
* * * 第9行
练习:
1. 接收用户输入的一个字符串:h, w 代表矩形的长和宽,打印一个空心的矩形
2. 输出九九乘法口诀
例:
接收用户输入的数字,计算该数字的阶乘
练习:
输入n, 计算1到n的阶乘之和
例:找1000以内最大平方数
例:给定一个字符串 target = 'hello huice',从中找出第一个不重复的字符,输出它是第几位
练习:去除上一题中的重复字符,得到一个新的字符串
作业:
1.一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同
2.打印出100-999中所有的"水仙花数",所谓"水仙花数"是指一
个三位数,其各位数字立方和等于该数本身。例如:
153是一个"水仙花数",因为153=1的三次方+5的三次方+3的三次方
3.输出100之内的素数总个数,所谓"素数"是指除了1和它本身以外,不能被任何整数整除的数,例如17
4.一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3.编程找出1000以内的所有完数
*Pycharm断点调试
------------------------------------------10、元组-------------------------------------------
字符串——数据结构:序列
另一种序列结构:元组
定义元组
方式一:
a = (1,2,3) --圆括号 逗号
方式二:
a = 1,2,3
特别地:
a = 1,
a = (1,)
访问元组对象
通过索引、分片
a = (1,6,4,8,3,5,6)
索引
print(a[0])
print(a[-1])
分片
print(a[2:6:1]
print(a[::-1]
元组中的元素值不允许修改!
a = (1,6,4,8,3,5,6)
a[0] = 2 错误!!!
元组属于不可变数据类型,要想改变某个值只能重新赋值,重新开辟内存空间创建新对象
(列表可以通过元素赋值修改某个元素,内存地址不变)
很多系统函数返回值为元组。
删除元组
del(元组名)
删除整个元组
元组运算符
+ 连接: tup3 = tup1 + tup2;
*N 复制并连接: 重复N次 tup3 = tup1 * 3
内置函数作用于元组
len(tuple):计算元组元素个数。
max(tuple):返回元组中元素最大值。
min(tuple):返回元组中元素最小值。
将其他序列转为元组:
tuple(seq):将其他类型序列转换为元组。
元组操作
index : T.index(target)
获取元素在元组中的索引值,对于重复的元素,默认获取从左起第一个元素的索引值
找不到时报ValueError
count : T.count(target)返回元组中某元素的个数
元组中的数据类型
任意,不必一致
元组嵌套 和 多维元组
多维元组
((1, 2, 3), (4, 5, 6))
如何取到每个元素?
元组嵌套
可以嵌套任何数据类型
*元组虽然是不可变数据类型,但是当元组中嵌套可变元素时,该可变元素是可以修改的,元组本身不变
([1, 2, 3], (4, 5, 6))
作业:员工工资表,查询结果集如下:((1, 'zhangsan', 3000), (2, 'lisi', 2500), (3, 'tiantian', 20000))
1.计算员工的平均工资
2.输出工资最高的员工姓名
------------------------------------------11、列表-------------------------------------------
列表--可变数据类型
列表属于可变数据类型,可以增加元素,可以通过赋值的方式改变元素的值,且内存地址不变
列表中可保存的数据类型
可以保存任何数据类型--数据项不需要具有相同的类型
列表的创建
[]
访问数据项
索引
分片
更新数据项
索引赋值
list[idx] = value
注意: 不能超过索引范围
追加元素
单个元素追加 list.append(ele)
追加一个列表中的所有元素 +=
不太常用的方式:list[x:x] = list2
固定写法,第x项后插入一个列表的所有元素
注:与分片赋值区分开
分片赋值
变化: x:
x:y
批量删除 和 清空列表
list[x:y] = []
list[:] = []
删除数据项
del(list[index])
del(list[x:y])
del(list) 不加索引直接删除引用,回收对象
列表方法
有返回值和无返回值
list.count() 有返回值
list.append() 原地操作,改变了对象本身
list.append(obj) 用于在列表末尾追加新的元素或对象 直接操作对象,无返回值
list.insert(index, obj) 将元素或对象插入到列表指定项
list.extend 在列表末尾一次性追加另一个序列中的多个值,相当于+=
list.count 用于统计某个元素在列表中出现的次数
list.index 用于从列表中找出某个值第一个匹配项的索引位置
list.pop 该方法从列表中弹出一个元素,默认是最后一个。并且返回弹出的元素;参数为下标,指定要弹出的元素
list.remove 从列表中移除某个值的第一个匹配项。与pop不同的是,该方法并不返回移除的元素, 并且参数
为要移除的元素
list.reverse 该方法对序列反向存放。注意该方法改变了列表但是没有返回值
reversed函数:并不返回一个列表,而是返回一个迭代器对象,使用list把迭代器对象转换成列表
list.sort 用于在原位置对列表进行排序。 在原位置意味着列表会被修改
注意:sort()方法的返回值并不是序列本身,而是None
修改排序规则
reverse参数
reverse 默认为False--按照ASCII码的升序排列,reverse=True降序
key参数
key = 函数名
key = len
key = mysort
函数为接收单参数的函数,能逐个接收 list 中的每个元素,经过运算后返回一个值
该值就作为排序的依据
key = lambda x: xxx
保存原序列顺序而进行排序
1.拷贝后再排序
2.内建函数:sorted()
sorted(seq, reverse=True/False, key=fun)
第一个参数是一个序列(或无序的队列如字典)
key指定一个接收单参数的函数,这个函数接收序列中的每个元素,经过运算后返回一个值
该值就作为排序的依据。默认为None
reverse是一个布尔值。如果设置为True,列表元素将被倒序排列
返回值是一个对序列中元素进行排序后的列表(list)
练习:一行代码输出[[1, 'zhangsan', 3000], [2, 'lisi', 2500], [3, 'tiantian', 20000]] 工资最高人的姓名
练习:
1.检查get请求的参数中是否包含sign,如果包含将参数值替换为空格,重新拼接为参数字符串
title=华为春季新品发布会&sign=2&limit=100&status=0&address=国家会议中心&time=2018-03-28
作业:
1.用python实现冒泡排序
# [50,20,30,10]
#
# 升序:谁大谁交换到后面
# 降序:谁大谁交换到前面
#
# 以升序为例
# 第1趟:
# [20,50,30,10]
# [20,30,50,10]
# [20,30,10,50]
# 第2趟:
# [20,30,10,50]
# [20,10,30,50]
# 第3趟:
# [10,20,30,50]
2.用python实现选择排序
# 定义:选择法排序指每次选择所要排序的数组中的最大值(由小到大排序则选择最小值)的数组元素,
# 将这个数组元素的值与最前面没有进行排序的数组元素的值互换
# 以升序为例:
#
# 原始:
# lst = [50, 30, 10, 20]
# 比较:
# 第一趟:[10, 30, 50, 20]
# 第二趟:[10, 20, 50, 30]
# 第三趟:[10, 20, 30, 50]
3.接收用户输入的数字,输入负数时结束输入。存入一个列表
然后找出用户所输入的所有数字中最大的数,最小的数,再将所有数字从小到大排序输出
迭代整个列表:
for x in list:
print(x)
for x in range(len(list)):
print(x)
(了解)[x for x in list] --迭代后自动装填成新列表
练习:
1.
a=[1, 2, 3, 4, 5, 6]
一行代码实现对a中的偶数位置的元素进行加3后,组成的新列表
print([i + 3 for i in range(1, len(a), 2)])
运算
a = a + b 生成了一个新的列表存这两个列表的和
a += b 效果与extend()一样,向原列表追加一些新元素,在原有列表上增加
* [1,2,3] * 3
列表嵌套:
多维列表: [ [1, 2, 3], [4, 5, 6] ]
zip函数
它接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的zip对象。
若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同
练习:用zip函数组合出
((1, 'zhangsan', 3000), (2, 'lisi', 2500), (3, 'tiantian', 20000))
类型转换
其他对象转列表
list(str)
str.split(seperator)
eval(str)
列表转字符串
str(list)
''.join(list)
列表转元组
tuple(list)
*Set介绍
集合类型--无序不重复元素集
创建
set(序列对象) 或 {A,B,C} (Python3)
不支持索引和分片
可以循环
操作
添加一项 s.add('x')
删除一项 s.remove('H')
remove()用于删除一个set中的元素,这个值在set中必须存在,如果不存在的话,会引发KeyError错误。
discard()用于删除一个set中的元素,这个值不必一定存在,不存在的情况下删除也不会触发错误。
弹出首个 s.pop()
清空 s.clear() 清空后为空set
因为也被当做序列对象,所以可以转元组或者转列表
列表去重:
方式一:循环原始列表,创建新列表
方式二:利用Set
*方式三:利用字典
练习:把[1,2,3,1,2,3] 中的重复元素剔除。至少写出两种方式
练习:1.列表合并(用你能想到所有方法实现)
[1, 2, 3, 5, 6] [0, 2, 5, 7]
结果:[0, 1, 2, 3, 5, 6, 7]
2. 去掉列表[2, 5, 3, 9, 7, 3, 6, 9, 2]中的重复元素,剩余元素要与原列表中出现顺序一致。
# def my_sort(x):
# return list0.index(x)
#
# print(list(set(list0))
# print(sorted(list(set(list0)), key=my_sort)
作业:
1.大脚超市赊账人员名单如下:
['刘能', '王老七', '谢广坤', '赵玉田', '杨晓燕', '刘大脑袋', '王长贵', '谢飞机', '赵四', '王大拿']
大脚想移除掉里面的姓氏重复的人(不考虑复姓),但是对于每种姓氏大脚想保留最后出现的那个人。希望你来帮助她
['杨晓燕','刘大脑袋','谢飞机', '赵四','王大拿']
*2.调用慧测会议管理接口,需要填写一个参数sign-数字签名
sign的算法如下:
用户输入的参数中,去除username参数,将其余的参数按参数名的ASCII码降序排列,
在得到的参数字符串之前拼接上user=username值
组合成一个新的字符串,加密后作为sign
要求:用户入参如下:
address=beijing&limit=200&title=Huice_Test&time=2018-01-30&username=tianlaoshi
结果:user=tianlaoshititle=Huice_Test&time=2018-01-30&limit=200&address=beijing
------------------------------------------12、字典-------------------------------------------
字典是可变类型,
字典中的数据是无序的
一个字典条目的语法是 键:值 key value
任何不可变数据类型都可以作为条目的键
创建
{ } 、dict(key1=value1,key2=value2...)
键
必须独一无二(如果键重复存入,会被覆盖),值不必
只能是不可变类型(常用字符串和数字)
值
可以是任意数据类型
dic1 = {'name':'zhangsan', 'age': 18, 'address': 'beijing', 'xxx': 'hahaha'}
{'zhangsan':80, 'lisi':90}
访问数据项
通过key
dic[key]
如果key不存在,报KeyError
***没有索引!不能分片!
取值:
print(dic1['age'])
print(dic1.get('xxx'))
赋值:
dic1['age'] = 19
dic1['xxx'] = 'hahaha'
dic={}
dic['sdfafs'] = 'afsafd'
更新数据项
dic[key] = value
如果key不存在,就是新增数据项
练习:
1、把字符串”k1:1|k2:2|k3:3”处理成 python 字典的形式:{'k1': 1, 'k2': 2, 'k3': 3}
删除数据项
del dic[key] 删除键是'key'的条目
del dict 删除字典
字典方法
判断key存在
*in 、not in
*dict.keys() 返回一个包含字典所有KEY的列表(Python3中为dict_keys类型对象)
*dict.values() 返回一个包含字典所有value的列表(Python3中为dict_keys类型对象)
*dict.items() 返回一个包含所有(键,值)元组的列表(Python3中为dict_keys类型对象)
dic.pop(key)
删除键key的项并返回key对应的 value值
如果key不存在,报错
dict.clear() 删除字典中的所有项或元素
*dict.fromkeys(seq, val=None) 创建并返回一个新字典,以seq中的元素做该字典的键,val做该字典中所有键对应的初始值(默认为None)
*dict.get(key) 返回字典中key对应的值,若key不存在字典中,则返回None
adict.update(bdict) 将字典bdict的键值对添加到字典adict中
key存在,就更新value。key不存在就新增数据项
字典合并
运算
字典不支持拼接和重复操作符(+,*)
字典的比较操作
长度等、键等、值等
迭代
遍历字典的key
for key in adict.keys():
print(key)
遍历字典的value
for value in adict.values():
print(value)
遍历字典的项
for item in adict.items():
print(item)
遍历字典的key-value
for key, value in adict.items():
print('key=%s, value=%s' % (key, value))
练习:
把字典{'k3': 3, 'k2': 2, 'k1': 1}处理成字符串的形式: k1:1|k2:2|k3:3”
排序
字典是无序的,排序后生成的是列表,或列表内嵌套元组
sorted(dic,value,reverse)
dic为可以迭代的对象,value 为排序的对象(这里指键或键值)
reverse:注明升序还是降序,True--降序,False--升序(默认)
键排序
--sorted(dict.keys())
值排序
--sorted(dict.values())
项排序,按照键或按照值
--sorted(dict.items(), key=lambda item:item[0])
--sorted(dict.items(), key=lambda item:item[1])
scores = {'zhangsan': 98, 'lisi': 85, 'wangwu': 90}
(1) 对所有名字排序,按ASCII升序排列
sorted(scores.keys())
(2) 对所有成绩排序,按照高低分排列
sorted(scores.values(), reverse=True)
(3) 对所有人和成绩排序,按照名字的ASCII码降序排列
[('zhangsan', 98), ('lisi', 85), ('wangwu',90)]
sorted(scores.items(), key=lambda x:x[0], reverse=True)
(4) 对所有人和成绩排序,按照名字的长度升序排列
sorted(scores.items(), key=lambda x:len(x[0]))
(5) 对所有人和成绩排序,按照高低分排列
sorted(scores.items(), key = lambda x:x[1], reverse=True)
类型转换
其他类型转字典:
字符串:eval(str)
列表:
二维列表转换
lst = [('name', 'zhangsan'), ('age', 18)]
print(dict(lst))
手动构造
lst1=['name', 'age']
lst2=['tianlaoshi', 18]
dic = {}
for i in range(0,len(lst1)):
dic[lst1[i]] = lst2[i]
print(dic)
利用zip
zip() --内建函数
它接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个tuple(元组)
*与dict() 连用,完成list组合成字典
lst1=['name', 'age']
lst2=['tianlaoshi', 18]
print(dict(zip(lst1,lst2)))
字典转列表:
list(dic) == dict.keys()
dict.keys() dict.values()
字典转元组:
tuple(dic) -- 只包含key值
字典转字符串:
str(dic)
练习:
编写一组数据,记录组内每个人的语文成绩
data = {
'ZhaoLiYing': 60,
'FengShaoFeng': 75,
'TianLaoShi': 99,
'TangYan': 88,
'LuoJin': 35,
'LiuLaoShi': 100
}
a.算出平均分
b.再找出学霸
编写一组数据,记录组内每个人的语文成绩、数学成绩、英语成绩
data = {
'ZhaoLiYing': [60, 68, 45],
'FengShaoFeng': [10, 28, 5],
'TianLaoShi': [44, 86, 73],
'TangYan': [99, 95, 95],
'LuoJin': [98, 65, 100],
'LiuLaoShi': [77, 97, 65]
}
a.找到平均分不足60分的人
b.找出各科的最高分
c.算出各科的平均分,再找出各科的学霸
作业:
1.编写一组数据,记录组内每个人的语文成绩、数学成绩、英语成绩
data = {
'颖宝':{'语文':60, '数学':68, '英语':45},
'冯威':{'语文':10, '数学':28, '英语':5},
'糖糖':{'语文':44, '数学':86, '英语':73},
'咕噜':{'语文':99, '数学':95, '英语':95},
'田老师':{'语文':98, '数学':65, '英语':100},
'刘老师':{'语文':77, '数学':97, '英语':65},
}
a.找到平均分不足60分的人,
b.找出各科的最高分,平均分
c.找出各科的学霸
2.统计一篇英文文章每个单词的出现频率,并返回出现频率最高的前5个单词及其出现次数(字典形式)
A small sample of texts from Project Gutenberg appears in the NLTK corpus collection. However, you may be interested in analyzing other texts from Project Gutenberg. You can browse the catalog of 25,000 free online books at http://www.gutenberg.org/catalog/, and obtain a URL to an ASCII text file. Although 90% of the texts in Project Gutenberg are in English, it includes material in over 50 other languages, including Catalan, Chinese, Dutch, Finnish, French, German, Italian
3.给定一个字符串,例如abcabcd,请你求得到该字符串中所有的长度大于等于2的子串,
并统计每个字串出现的次数
------------------------------------13、函数-------------------------------------
作用:1.代码复用,常用功能封装成函数;2. 模块化开发
特点:定义处暂不执行函数体中的内容,调用时才执行
内置函数
id(), type(), len(), max(list),
1、绝对值:abs(-1)
2、最大最小值:max([1,2,3])、min([1,2,3]),对序列进行操作
3、序列长度:len('abc')、len([1,2,3])、len((1,2,3))
4、乘方:pow(2,3,4) // (2**3) % 4
5、浮点数:round(3.1415926, 2) //3.14 四舍五入
6、类型转换函数:int()、str()、list()....
匿名函数-lambda
def func(x,y):
return x+y
func = lambda x,y:x+y
创建函数
def 函数名(参数列表):
函数体语句
函数的命名规则:
一个单词--直接小写
多个单词--每个单词小写,以下划线分隔
enroll
submit_info
verify_password
文档化说明
函数首行加 '' 或 ''' '''
函数名.__doc__ 可以查看函数文档 系统内建参数
测试用例中,用于输出用例描述
callable(函数名) --判断函数是否可以被调用
debug的时候经常报错,xx is not callable
--说明你应该在报错的地方给一个函数,结果你给的xxx不能当函数用
1.文件中定义的某个变量名与系统函数名重复,
pass--占位
函数的参数 arguments
实参和形参
传参时,可以指定参数名
def my_function1(name, address, age):
print('姓名:%s, 地址:%s, 年龄:%s' %(name, address, age))
1 不指定参数名
my_function1('zhangsan', 'beijing', 10)
2 出错的情况:参数数量大,顺序记不住,不想按顺序写
my_function1('lisi', 10, '男')
3 指定参数名,即使顺序不一致也没关系
my_function1(age=10, address='shanghai', name='王五')
参数默认值
*定义函数时 可指定参数的默认值
没有默认值时:
def my_function2(name, age):
print('姓名:%s, 年龄:%s' % (name, age))
调用时,传参数量与定义时不一致:
my_function2('tianlaoshi') #会报错,给出的参数数量与要求不一致
定义时没有指定参数默认值,则只能严格按照定义时的数量传参
my_function2('tianlaoshi', 46)
定义函数时,可以给一些数值相对固定的参数以默认值,赋值给形参
def my_function2(name, age=18):
print('姓名:%s, 年龄:%s' % (name, age)
调用时若不给相应形参传值,则自动取用默认值;
若传值,则覆盖默认值
my_function2('张老师')
my_function2('田老师', 46)
*有默认值时的参数顺序
*错误举例:
def enroll(gender, age=6, city='Beijing', name): #SyntaxError: non-default argument follows default argument
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
print('-------------')
enroll('男', 'tiantian')
**结论:带默认值的参数往后放,后面不能再有必填参数
def enroll(gender, name, age=6, city='Beijing'):
*参数默认值的数据类型和初始化逻辑
默认值最好是不可变数据类型
如果是可变数据类型,默认为空要用None,别用空对象。
例:
以下的代码的输出什么? 你将如何修改 extendList 的定义所带来的隐患问题
def extendList(val, list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print("list1 = %s" % list1)
print("list2 = %s" % list2)
print("list3 = %s" % list3)
# 隐患和修改方法:
# 函数定义时,如果参数有默认值,则在定义时就会开辟一块内存空间来存储该默认值
# 调用函数时,如果未给有默认值的参数传值,就会使用该内存空间的数据
# 多次调用时,该空间就会被重复使用,如果某一次调用时改变了该空间的数据,其他次调用也会收到影响
# 可变数据类型,内存空间地址可以被改变,所以尽可能不用可变数据类型
# 如果一定要用,默认值不要用空对象,应该用None
def extendList(val, list=None):
if list == None:
list = []
list.append(val)
return list
可变参数
传入的参数个数是可变的
*params
在函数内部,参数numbers接收到的是一个tuple或list
在函数调用时,可以一个一个的传,也可以传list或tuple --*params
**params
在函数内部,参数numbers接收到的是一个dict
在函数调用时:
可以一个一个的传 key=value
也可以传dict --**params
**参数定义的顺序必须是:必选参数、带默认值参数、可变参数
关于返回
见到return 函数就结束
不写return无返回--None
只写return 返回None
返回多个值--实际返回的是元组
练习:
1. 写函数,判断用户传入的序列(字符串、列表、元组)长度是否大于5
2. 写函数,输入一个列表(列表元素均为数值型),返回列表元素的平均值
3. (选做)编写一个生成get请求地址的函数,上游传递过来的参数有url=“”,domain=“”,data={},
请根据以上参数返回一个get请求的完整链接,其中data和url有可能不传
http://127.0.0.1/access/log?a=1&b=2
domain url data {'a':1,'b':2}
def gen_get_address(domain, url=None, data=None):
address = 'http://' + domain
if url:
address += '/' + url
if data:
params_list = []
for k, v in data.items():
param = k + '=' + v
params_list.append(param)
params = '&'.join(params_list)
address += '?' + params
return address
print(gen_get_address(domain='127.0.0.1',
url = 'huice/huice',
data={'usr': 'tiantian', 'passwd': 'bugaosuni'}))
http://127.0.0.1/huice/huice?passwd=bugaosuni&usr=tiantian
递归
如果一个函数在内部调用自身,这个函数叫做递归函数
递归调用的次数过多,会导致栈溢出
练习:
1.求一个数n的阶乘
函数式编程--函数的参数是函数
高阶函数
def f():
pass
def fun(x, y, f):
pass
map():函数接收两个参数,一个是函数,一个是序列
将传入的函数依次作用到序列的每个元素,并把结果作为map对象返回
应用:并行遍历--序列合并
filter():“筛选”函数
接收一个布尔值返回值的函数和一个序列,
把传入的函数依次作用于每个元素,根据返回值是True还是False决定保留还是丢弃该元素
练习:
1.利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。
输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']
---------------------------14、类和对象-----------------------------------------------------------------------------
面向对象
面向过程
生活中的例子
蛋炒饭 怎么来做
蒸米饭,煎鸡蛋 一起炒 面向过程
人 米饭 鸡蛋 锅 油 盐 葱花 西红柿 一切皆对象
Java - 强制面向对象 类
Python - 既支持面向对象,也支持面向过程
*if __name__ == '__main__' 该如何理解?
只有单独运行本文件时,该if条件下的语句块才会被执行
__name__ 是内置变量,用于表示当前模块的名字
如果一个模块被直接运行,其 __name__ 值为 __main__
类是对某一类具有共同特点的事物的抽象,是在概念上的一个定义
比如:动物,人,学生。但是单独说这三个概念的时候,不代表任何一个具体的个体
类 属性 名字 身高 体重 变量
行为 吃饭 学习 函数 方法
属性 成员
类
行为 成员
类
成员方法定义时都要有self参数,但调用时不需要传值
类的具体实例叫做 【对象】 【类的实例】 【实例化一个类】
学生是类,张三是一个具体的学生就是 学生类的实例(Instance),也叫学生对象
学生 慧测的学生 类
张三 对象 实例
#变量 属性
身高 成员变量 实例变量
体重
学校='huice' 类变量
学费=500
#方法 行为、功能
学习 成员方法 实例方法
上学 类方法
类的定义:
class 类名(父类):
类实体
*类名:每个单词的首字母大写
属性的定义:
成员变量
构造函数(初始化函数) __init__(self)
作用:python在创建类的实例的时候,会首先调用这个类的__init__()方法
初始化数据
self:创建的实例自身(存储当前对象的地址)
所有的成员方法第一个参数默认是self,但是调用的时候不需要为self传值。
只要用类的实例调用成员方法,默认相当于已经给self传值了。
类的属性:变量
成员变量--属于实例的变量
每次实例化就创建,实例结束就销毁
*一般是在__init__方法中通过self完成 定义
*类内部:通过self访问,类外部:通过实例名访问
类变量
属于类自己的变量(保存在内存),每次被构造的时候,拷贝一个副本给对象
*在类起始处统一定义
*通过类名或实例来访问
通过实例的修改只对当前实例生效,通过类名的修改才能改变整个类所有对象的值
类的操作:方法
成员(实例)方法
定义:必须带有参数self
内部:可以访问成员变量、类变量(self或类名)、成员方法(self)、类方法(self或类名)
通过self调用
外部:通过类实例调用
类方法
定义:必须带有@classmethod、和cls参数
内部:可以访问类变量、类方法
外部:通过类实例或类名调用
静态方法
定义:必须带有@staticmethod
内部:如果静态方法调用类方法或属性时,只能直接类名.属性名或类名.方法名
外部:通过类实例或类名调用
------------------------------------------------------------
总结:类由属性和方法组成
分类
定义
调用
------------------------------------------------------------
访问限制
私有变量:__变量名
python使用的是名字重整技术,改变了私有变量的值:_类名__变量名
专属变量
__xx__
私有方法:
__xx()
私有变量和方法,在类的内部访问不受限制。
特殊方法:
__xx__() 代表一定的协议,相当于Java中的接口方法
* __str__()与__repr__()
__str__() --让class作用于print()函数
(了解即可)__repr__() --返回程序开发者看到的字符串
* __len__() --让class作用于len()函数
__iter__() --让class具有可迭代的属性,返回值必须是对象自己
next():每一次for循环都调用该方法
__getitem__() --让class作用于索引方式
__getattr__()
当调用不存在的属性时,会试图调用此方法,来尝试获得属性
封装
变量私有化 + 提供getter和setter方法
练习:
1.设计一个汽车类Auto,
有速度属性speed,启动start、加速speedup(1次速度+10)和停止stop(1次速度-30)方法;
作业:
1.设计一个汽车类Auto,
属性:品牌brand
颜色color
速度speed,初始为0
方法:启动start,打印‘yyyy色的xxxx启动了’,xxxx为品牌,yyyy为颜色
加速speedup(加速数值支持通过参数传入)
减速slowdown(减速数值支持通过参数传入)
2.设计一个子类Bus表示公共汽车,Bus增加一个属性passenger表示乘客数量。
另外在添加两个方法gotOn和gotOff表示乘客的上车和下车;
通过main方法完成对Auto和Bus的使用
3.利用列表实现数据结构--栈
pop
append
有极限大小
可以弹栈
可以压栈
后进先出
栈满时压栈,提示已满
栈空时弹栈,提示为空
要求:
0.不能直接访问栈
1.初始化函数,传入栈的极限大小
2.提供一个弾栈和一个压栈的方法
3.提供一个获取栈极限大小的方法
4.其他方法私有--判断栈是否到达极限,栈是否为空
继承和多态
继承
方法覆盖(重写)
1.当我们需要传入一个对象时,我们可以不传入具体的类型,而传入一个抽象的概念---父类对象
2.这样,在程序实际运行时,可以动态绑定传入的类型
3.因为都有共同的父类,所以一定有共同的方法。使用时,内部使用时,调用共有的方法就可以
isinstance(instance, class)方法
多重继承
(class1, class2, class3) --class1优先
作业:
设计一个部门类Department,属性为部门名称(name)
需求:
1.直接通过Department调用get_all方法,返回公司员工总数
2.通过部门实例,调用方法get_count方法,返回部门员工数
3.通过部门实例,调用方法get_employees(),显示该部门所有员工信息
格式为: 工号-xxx ,姓名-xxx ,手机号-xxx,工资-xxx
提示:有人入职,员工数就要增加,部门存入员工对象
设计一个员工类Employee,员工属性有姓名(name)、手机号(phone)、工资(salary)、所属部门。
需求:
1.新员工入职时,分配一个不重复的工号。从1开始排列,已离职员工工号作废。
2.员工本人可以调用get_salary方法查询自己的工资
3.员工本人可以调用get_info方法查询自己的全部信息--字典形式
测试:人力资源部(小红)、技术部(田老师、刘老师)
输出 每个部门的人员和公司总人数,输出两个部门的人员信息
----------------------------------------15、异常------------------------------------------------------------------------------------
在程序运行过程中,总会遇到各种各样的错误
有的错误是程序编写有问题造成的
还有一类错误是完全无法在程序运行过程中预测的
举例-各种类型的异常
调试时我们关心
什么类型的错误? 分类
在哪儿出错的? 记录并显示文件、行数、代码
为什么出错? 错误的具体说明,显示原因
抛出的异常也是对象
异常的分类
系统定义的异常
BaseException 所有异常的基类
Exception 常规错误的基类
StandardError 所有的内建标准异常的基类
ImportError 导入模块错误
ArithmeticError 所有数值计算错误的基类
FloatingPointError 浮点计算错误
AssertionError 断言语句失败
AttributeError 对象没有这个属性
Warning 警告的基类
异常处理
不做处理,出现异常程序直接断掉
需求:出现错误时,希望后面代码还能执行
捕获 try except finally
格式:
try:
可能会发生错误的语句块
except:
发生错误后跳转到该语句块执行
finally:
不管有没有发生错误,都会跳转到此处,语句都会被执行
收尾、资源释放工作,如关闭文件、流等
有return时,先执行finally中的语句,然后再return
执行顺序:
当我们认为某些代码可能会出错时,就可以用try来运行这段代码
如果执行出错,则 try 语句块中的后续代码不会继续执行,而是直接跳转至错误处理代码,即except语句块
执行完except后,如果有finally语句块,则执行finally语句块
try except 语句块可以相互嵌套
except:
0.后面可写要捕获的异常类型,不写异常类型代表捕获一切类型的错误
1.如果不确定会发生什么类型的异常,可以抓所有,或抓父类
2.后面可以写多个异常类型,都会捕获 (exception1, exception2)
3.可以在except语句块后面加一个else,当没有错误发生时,会自动执行else语句
4.可以用变量(如e)代表当前异常的实例 print可以显示错误信息 , e or as e
5.如果想要输出详细堆栈信息,使用import traceback traceback.print_exc()
程序不会终止运行
利用异常实现分支
例:
a = [1,'a','c',10,23] 只使用try...catch,统计出a列表中有几个非整数
非整数 - int()时会抛出异常
counter = 0
for ele in a:
try:
int(ele)
except:
counter+=1
print(counter)
练习:
1.从开发的代码库中得到一组数据,表示每个文件的代码变更情况
{'login.py': 'a 8 d 2 u 3 ', 'order.py': 'a 15 d 0 u 34', 'info.py': 'a 1 d 20 u 5 '}
其中 a表示新增行数,d表示删除行数,u表示修改行数。login.py的变更行数为13
要求:统计出每个文件的变更行数
2.优化练习
接受用户输入的一个字符串,如果是正整数就判断是否能同时被3和7整除
抛出
自动抛出:
如果错误没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误信息,然后程序退出
手动抛异常:
def sum(a,b):
if a==0 or b==0:
raise BaseException('不能为0')
else:
return a+b
raise 异常类名 (错误信息)
总结:函数对异常的的两种处理:
上抛——交由调用它的函数或一直上抛给解释器处理
捕获
*选择捕获还是抛出?
如果有能力处理异常,不是导致系统崩溃的,程序必须断掉的,非抛出不可的异常,
应对异常进行捕获处理,给用户友好的合理的可控的返回值。
*综合使用:捕获,补充信息,再上抛——异常的二次处理
需求:1.替换系统自动抛出的提示信息,但要求抛出异常时程序停止运行。
def div(a, b):
try:
return a/b
except:
raise BaseException('除数不能为0')
div(2,0)
需求:2.不是把异常信息打印到控制台,而是可以用来记录系统日志,需要捕获
except中可以写记录日志的代码,记录完再抛出
对比:两种不同的处理方式
def div(a, b):
try:
return a/b
except BaseException('除数不能为0') as e:
print(e)
return 0
自定义异常
系统定义的异常不可能覆盖全部情况,
可自己定义,可继承系统异常
创建类,继承相应系统异常即可
练习:
1.编写一个计算减法的方法,当第一个数小于第二个数时,抛出“被减数不能小于减数”的异常
2.编写一个计算加法的方法,接收键盘输入的两个数字,进行加法运算,当输入的有非数字时,通过异常处理机制使程序正常运行(返回0)
3.创建一个用户注册服务,其中有一个register方法。当用户名小于6位时,抛出自定义异常
系统异常NameError的子类异常UserNameError
----------------------------------16、模块-------------------------------------------------------------------------------------
在Python中,一个文件就称之为一个模块(Module)
可以作为module的文件类型有: ".py"、".pyo"、".pyc"、".pyd"、".so"、".dll"
导入--使用其他模块中的代码
如何导入?
最基本的:import xxx
导入xxx模块后,我们就有了变量xxx指向该模块,利用这个变量,就可以访问xxx模块的所有功能
导入的作用?
导入的模块是用于定义的--定义类、变量、函数
首次导入会运行模块中的代码
*如果有导入时不希望执行的代码,可以放在if __name__ == '__main__'条件语句下
*再次导入不会运行。除非使用reload(模块名)函数
导入的几种情况
*导入文件
import student #python文件不用写.py
使用文件中的类、方法
student.Student()
student.Student().成员变量和成员方法
student.Student.类变量和类方法
student.sum()
*导入类、导入方法
即:从文件中导入类、方法
from student import Student
from student import sum
from student import Student, sum
使用类、方法
Student()
Student().成员变量和成员方法
Student.类变量和类方法
sum()
*重名的情况
from student import Student, sum
from huice import sum
*涉及包时的导入
*什么是包?
将多个.py文件组织起来,以便在外部统一调用
包含__init__.py文件的文件夹
__init__.py: 包的初始化文件。当包或包下的内容(子包、文件、文件中的类/方法/变量被加载时,
会执行该文件中的代码
不包含__init__.py的,是普通文件夹,其中的内容不能被导入
包可以嵌套多层
完整的模块名 = 包名.子包名.模块名
*从包中的文件中导入类、方法
from day111.day1111.student import Student,ordinary_method
from 完整模块名 import 类名,方法名
*从包中导入文件
from day111.day1111 import student
from 完整包名 import 模块名
*从包中导入子包
from day111 import day1111
from selenium import webdriver
意义:如果包中的__init__.py中导入了其他文件中的类、方法,则可以直接使用"包名."的方式
使用这些类
解释器如何找到的模块?
1.首先在当前目录查找
2.当前脚本指定的sys.path --python搜索模块的路径集合
可以在python 环境下使用sys.path.append(path)添加相关的路径,但在退出python环境后自己添加的路径就会自动消失
3.环境变量 --PYTHONPATH
4.安装设置相关的默认路径
built-in --内建模块
'''C:\Python27\Lib --所有python类库的总目录'''
标准库模块
email、json、csv、httplib、io....
site-packages --第三方包(包括自定义)
5.在任一步骤,找到名称符合的就停止,不再继续寻找
如果我们要引入自定义的模块:
0.在一个目录中直接import名称
1.添加自己的搜索目录,有三种方法:
第一种是直接修改sys.path,添加要搜索的目录:
import sys
sys.path.append('/Users/my_py_scripts')
但在退出python环境后自己添加的路径就会自动消失
第二种方法是设置环境变量PYTHONPATH
第三种方法是将包放到python安装目录的Lib下或sitepackage下(不推荐)
关于from A import *的坑
__all__ = ['module_13', 'module_12']
使用别名
import xxx as X
应用:统一变量名
例:
try:
import json python >= 2.65
except ImportError:
import simplejson as json python <= 2.5
练习:新创建一个子包 sub
sub中有一个模块:util.py 其中有一个工具类:Util,有一个静态方法求两数之和;一个类方法求两数之积
如果单独运行该文件,显示说明文字
在当前包下的demo.py文件中调用这些方法
----------------------------------17、常用标准库-------------------------------------------------------------------------------------
os --对目录或文件操作
变量
os.environ --以字典形式返回系统环境变量
函数
os.system(command) --执行命令行(运行外部程序),不能存储结果
os.startfile(path) --windows特有,模拟双击打开文件
mac/linux-- subprocess.Popen(path)
**os.popen(command) --执行命令行,并返回一个文件对象
os.getpid() --返回当前进程ID
操作目录(文件夹):
os.getcwd() --得到当前工作的目录
os.listdir() --指定目录下所有的文件和目录名
os.mkdir() --创建目录,已存在报错
os.makedirs() --创建多级目录
os.rmdir() --删除指定目录,只能是空目录(不能有文件或子目录)
os.removdirs() --删除多级目录,只能是空目录
os.chdir() --改变目录到指定目录
os.path.isfile() --判断指定对象是否为文件。是返回True,否则False
os.path.isdir() --判断指定对象是否为目录。是True,否则False
os.path.exists() --检验指定的对象(文件)是否存在
os.path.split() --返回路径的目录和文件名
os.path.join(path, name) --连接目录和文件名
os.path.dirname(path) --返回path中的文件夹部分
os.path.basename(path) --返回文件名
os.path.abspath(path) --获得绝对路径
练习:
report文件夹中,是所有自动化测试报告的存放路径。
编写new_report函数,传入路径。返回最新一份报告的文件名(完整路径+文件名)
1.报告以时间戳命名
*2.报告不以时间戳命名
操作文件:
os.path.getmtime(path) --文件或文件夹的最后修改时间,从新纪元到访问时的秒数
os.path.getctime(path) --输出文件最近访问时间
os.path.getsize(path) --文件或文件夹的大小,若是文件夹返回0
os.remove(path) --移除文件
os.rename(old, new) --重命名文件或目录
os.chown(path, uid, gid) --改变文件或目录所有者
os.chmod(path, mode) --改变文件访问权限
os.chmod('/home/user/c/a.tar.gz', 0777)
shutil --高级的 文件、文件夹、压缩包 处理模块
shutil.copyfile(src, dst) --拷贝文件,如果当前的dst已存在的话就会被覆盖掉
shutil.copy(src, dst) --拷贝文件和权限
shutil.copytree(src, dst) --递归地拷贝文件
shutil.rmtree(src) --递归删除一个目录以及目录内的所有内容
time --提供了各种操作时间值
time.time() 获取当前时间时间戳--秒
time.ctime(seconds) 根据秒数取时间戳--美式时间格式
time.asctime([tuple]) 根据时间元组,获取时间戳--美式时间格式
time.localtime(seconds) 将秒数转换成一个时间值元祖
time.mktime(tuple) 将一个时间值元组转换成秒数
time.sleep(seconds) 延迟执行给定的秒数
*time.strftime(format[,tuple_time])
根据传入的格式化字符串,将tuple时间格式化为指定的格式
tuple_time可以不传,不传返回当前时间格式化后的结果
python中时间日期格式化符号:
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
应用:获取当前时间字符串:time.strftime('%Y-%m-%d %H:%M:%S')
time.strptime(string, format)
传入的时间为字符串
按照传入的format解析字符串时间为tuple格式的时间
random --生成随机数
random.uniform(a,b) 返回a和b范围内的随机实数 [a,b)
random.randint(a,b) 返回整数a和b范围内数字 [a,b]
random.random() 返回随机数,它在0和1范围内(不包括1)
random.randrange(start, stop[, step]) 返回整数范围的随机数
random.sample(seq, x) 从序列或set、dict中返回随机x个元素(若为字典只返回key) - -列表形式
random.shuffle(list) 给指定的列表进行原地随机移位
random.choice(seq) 从序列seq中随机选择一个元素
练习:
0.编写一个方法,输出当前时间三天前的时间点,格式:2017-05-01_13:59:06
1.编写一个方法,根据传入的美式时间字符串(13:28:06_12/21/2018),生成标准时间字符串(2018-12-21_13:28:06)
作业:
1.编写一个方法,接受参数为一个列表:[2017, 01, 15] (不考虑1970.1.1之前的时间点)
随机输出2017.1.15日 00:00:00 之前的一个时间点,格式为:2017-01-01_13:59:06
2.用python脚本,写一个斗地主的发牌程序
3个人每人17张,三张底牌归地主所有
要求:函数返回一个字典,{地主:[], 农民1:[], 农民2:[]}