Python基础知识
一、Python语言基础
1.数字
1.1.运算符优先级
序号 | 运算符 |
---|---|
1 | 圆括号 |
2 | 幂运算符 ** |
3 | 负号 - |
4 | 乘 *、除 /、整除 //、取余 % |
5 | 加 +、减 - |
1.2.
- 数字分为整数int、浮点数float、复数complex
- Python中支持处理大整数,不会溢出
- 二进制 0b (bin)
- 八进制 0o (oct)
- 十六进制 0x (hex)
1.3.数字格式化输出 format
- format的返回值是字符串类型
- 第一个参数是要格式化的数字,第二个是表示格式的字符串
数字 | 格式 | 输出 | 描述 |
---|---|---|---|
3.1415926 | {:.2f} | 3.14 | 保留小数点后两位 |
3.1415926 | {:+.2f} | +3.14 | 带符号保留小数点后两位 |
-1 | {:+.2f} | -1.00 | 带符号保留小数点后两位 |
2.71828 | {:.0f} | 3 | 不带小数 |
5 | {:0>2d} | 05 | 数字补零 (填充左边, 宽度为2) |
5 | {:x<4d} | 5xxx | 数字补x (填充右边, 宽度为4) |
10 | {:x<4d} | 10xx | 数字补x (填充右边, 宽度为4) |
1000000 | {:,} | 1,000,000 | 以逗号分隔的数字格式 |
0.25 | {:.2%} | 25.00% | 百分比格式 |
1000000000 | {:.2e} | 1.00e+09 | 指数记法 |
13 | {:>10d} | 13 | 右对齐 (默认, 宽度为10) |
13 | {:<10d} | 13 | 左对齐 (宽度为10) |
13 | {:^10d} | 13 | 中间对齐 (宽度为10) |
数字 | 格式 | 输出 |
---|---|---|
11 | ‘{:b}’.format(11) | 1011 |
11 | ‘{:d}’.format(11) | 11 |
11 | ‘{😮}’.format(11) | 13 |
11 | ‘{:x}’.format(11) | b |
11 | ‘{:#x}’.format(11) | 0xb |
11 | ‘{:#X}’.format(11) | 0XB |
x = 1234.56789
# 小数点后保留两位数,输出结果:'1234.57'
print(format(x, '0.2f'))
# 数字在12个字符长度的区域内右对齐,并保留小数点后1位数字,输出结果:' 1234.6'
print(format(x, '>12.1f'))
# 数字在12个字符长度的区域内左对齐,并保留小数点后3位数字,紧接着输出20,输出结果:'1234.568 20'
print(format(x, '<12.3f'), 20)
# 数字在12个字符长度的区域内右对齐,并保留小数点后1位数字,数字前面补0,输出结果:'0000001234.6'
print(format(x, '0>12.1f'))
# 数字在12个字符长度的区域内左对齐,并保留小数点后1位数字,数字后面补0,输出结果:'1234.6000000'
print(format(x, '0<12.1f'))
# 数字在12个字符长度的区域内中心对齐,并保留小数点后2位数字,紧接着输出3,输出结果:' 1234.57 3'
print(format(x, '^12.2f'),3)
# 每千位用逗号(,)分隔,输出结果:1,234.56789
print(format(x, ','))
# 每千位用逗号(,)分隔,并保留小数点后2位数字,输出结果:1,234.57
print(format(x, ',.2f'))
# 用科学计数法形式输出数字,输出结果:1.234568e+03
print(format(x, 'e'))
# 用科学计数法形式输出数字,尾数保留小数点后2位数字,输出结果:1.23E+03
print(format(x, '0.2E'))
2.获取输入
2.1.
- 不管录入什么数据,imput函数都会以字符串形式返回
- imput的参数为等待输入时的提示输出
2.2.类型转换
函数 | 描述 |
---|---|
int(x) | 将x转换为十进制整数 |
float(x) | 将x转换到浮点数 |
complex(real [,imag]) | 创建一个复数 |
str(x) | 将对象 x 转换为字符串 |
list(s) | 将序列 s 转换为列表 |
tuple(s) | 将序列 s 转换为元组 |
chr(x) | 将整数x转换为字符 |
ord(x) | 将字符x转换为整数值 |
oct(x) | 将整数x转换为八进制字符串 |
hex(x) | 将整数x转换为十六进制字符串 |
4.字符串基础
4.1.
- 字符串用单引号或者双引号括起来
- 转义字符 \ 反斜杠,反斜杠后面的内容是字符串的一部分。例:\ 说明第二个\是字符
- 字符串加法,直接用+号将字符串连接起来
- repr函数或在字符串前写r 可以让字符串保持原始字符。
- 例:repr(“Hello\nWorld”)、r"Hello\nWorld",此时\n不会被转义,算作两个普通字符
- 在句尾写\可以将字符串写成多行
二、条件、循环和其他语句
1.输出、赋值、缩进
1.1.print函数:
print(a,b,c,d,e,f,g)
- 多参数之间首尾相接输出,默认有一个空格
- 参数最后添加sep=",",可以让默认的空格变成逗号(,)
- 参数最后添加end=" ",这就是将默认的换行结尾符换成了空格结尾
- 参数最后添加end="",这就是将默认的换行结尾符换成了长度为0的字符串结尾,也就是清除了换行效果
1.2.序列解包、链式赋值、增量赋值
- x,y=100,“a”;
- x=y=50;
- x+=20;
1.3.缩进
- 代码块的每行语句应该缩进同样的量
- 冒号代表代码块的开始,代码块中的每一条语句都是缩进的
- 当退回到与块相同的缩进量时,就表示当前块已经结束
2.条件和条件语句
2.1.布尔值和布尔变量
- 每一种类型的值都可以被解释成布尔类型的值
- True就是1.False就是0
- 可以用bool函数将其他类型的值转换为布尔类型的值
print(bool("")) #False
print(bool('')) #False
print(bool("Hello")) #True
print(bool([])) #False
print(bool([1,2,3])) #True
print(bool(0)) #False
print(bool(20)) #True
2.2.比较运算符
逻辑表达式 | 描述 |
---|---|
x==y | x等于y? |
x>=y | x大于或等于y? |
x<=y | x小于或等于y? |
x!=y | x不等于y? |
x is y | x和y是同一个对象? |
x is not y | x和y不是同一个对象? |
x in y | x是否是y中的成员? |
x not in y | x是否是y中的成员? |
- 字符串之间也可以用逻辑表达式来比较
- and or not 逻辑运算
- == 判断的仅仅是值,is判断的是是否指向同一个位置,同一个对象
2.3.if 、else、elif
从if 、else、elif到冒号(:)都是布尔类型的
2.4.assert 断言语句
value=20
assert value<10 or value >30,'value值必须在10~20之间'
直接抛出异常,异常原因:‘value值必需在10~20之间’
3.循环
3.1.range函数
- numbers=range(1,1000)则numbers=[1,2…998,999]
- for i in range (100) 则从0开始遍历99
3.2.
x=0
while x<100: #for i in range (100):
print(x) # print(i)
3.3.break跳出循环 continue跳出单次循环
一般都只放在if语句里
4.exec和eval
4.1.
- exec和eval功能相同,ecex没有返回值,eval会返回结果值
i={}
eval("print(a+b)",i,{'a':1,'b':2})
- 第一个参数print(a+b)代表要执行的字符串,i代表传参给i来计算,
{‘a’:1,‘b’:2}代表初始化要执行的变量,给变量传递什么值
三、列表和元组
1.定义序列
- 序列中可以是任何类型的值、变量、其他序列(构成二维序列)
names = ["Bill", "Mike"]
numbers = [1,2,3,4,5,6]
salary=[3000.0,4000.0,5000.0]
flags = [True,False,True,True]
values = [names,numbers,salary,flags,['a','b']]
for value in values:
print(value)
2.序列的基本操作
2.1.索引
- 字符串、序列,都可以直接添加索引
a=input()[2]
flags = [True,a,True,True]
print(flags[1][0]) #输入123,输出3
2.2.切片 也是左闭右开
- [a,b,c]
- a,b参数仅代表位置,c参数代表步长,c>0则切出a~b
- 若c<0,则说明从结尾开始切片,切出b~a
- 不写参数则说明没有限制,步长不能为0
2.3.序列的加法
- 序列和序列可以首尾相接,字符串和序列不可以直接相加
print([1,2,3] + [6,7,8]) # 运行结果:[1,2,3,6,7,8]
print("Hello" + " world") # 运行结果:Hello world
print([1,2,3] + ["hello"])
# 把字符串作为序列的一个元素,运行结果:[1,2,3,"hello"]
print([1,2,3] + ['h','e','l','l','o'])
# 运行结果:[1,2,3,'h','e','l','l','o']
print([1,2,3] + "hello")
# 抛出异常,序列不能和字符串直接相加
2.4.序列的乘法
- 用int n 乘以一个序列,会生成一个重复n次的序列
print('hello' * 5)
#hellohellohellohellohello
print([20] * 10)
# [20, 20, 20, 20, 20, 20, 20, 20, 20, 20]
- 序列的len、max、min函数
3.列表的基本操作
- 删除列表元素 del 无返回值 remove(值)返回被删除的数(只能删除第一次出现的位置)
- pop(位置) 删除参数位置的数并返回
- 切片赋值: 插入元素、删除元素、添加尾部元素
numbers = [1,6,7]
numbers[1:1] = [2,3,4,5]#相当于插入元素,但不会成为二维的
print(numbers)
# [1, 2, 3, 4, 5, 6, 7]
numbers[1:4] = [] #相当于删除元素
print(numbers)
# [1, 5, 6, 7]
numbers[9:] =number #相当于尾部添加元素
print(numbers)
#[1, 5, 6, 7, 1, 5, 6, 7]
4.列表方法
方法 | 作用 |
---|---|
append(x) | 返回列表最后插入新的值x的列表 |
clear() | 返回清空的列表 |
copy() | 返回一个相同序列 |
cout(x) | 返回x出现的次数 |
a.extend(x) | 无返回值,用于连接a和x |
index(x) | 返回x第一次出现的位置 |
insert(x,y) | 返回在x位置插入y的列表 |
pop(x) | 返回x位置的值,并删除该位置的元素 |
remove(x) | 返回删除第一次出现的x的新列表 |
reverse() | 返回倒置摆放的新列表 |
sord() | 返回升序排列的新列表 |
sorded() | 无返回值 |
print("----测试copy方法-----")
a = [1,2,3]
b = a # a和b指向了同一个列表
b[1] = 30 # 修改列表b的元素值,a列表中对应的元素值也会改变
print(a) # 运行结果:[1, 30, 3]
aa = [1,2,3]
bb = aa.copy() # bb是aa的副本
bb[1] = 30 # 修改bb中的元素值,aa中的元素值不会有任何变化
print(aa) # 运行结果:[1, 2, 3]
print("----测试extend方法-----") #列表+号效率低,不使用
a = [1,2,3]
b = [4,5,6]
a.extend(b) # 将b列表接在a列表的后面,extend方法并不返回值
print(a) # 运行结果:[1, 2, 3, 4, 5, 6]
print("----测试pop方法-----")
numbers = [1,2,3]
# pop方法返回删除的元素值
print(numbers.pop()) # 删除numbers列表中的最后一个元素值,运行结果:3
print(numbers.pop(0)) # 删除numbers列表中的第1个元素值,运行结果:1
print(numbers) # 运行结果:[2]
print("----测试sort方法-----")
numbers = [5,4,1,7,4,2]
numbers.sort() # 对numbers列表中的元素值按升序排序(默认)
print(numbers) # 运行结果:[1, 2, 4, 4, 5, 7]
values = [6,5,2,7,"aa","bb","cc"]
# 待排序列表的元素类型必须是可比较的,字符串和数值类型不能直接比较,否则会抛出异常
# values.sort() # 抛出异常
# 使用sorted函数
x = [7,6,4,8,5]
y = sorted(x) # 对x的副本进行排序
print(x) # 运行结果:[7, 6, 4, 8, 5]
print(y) # 运行结果:[4, 5, 6, 7, 8]
# sorted函数可以对任何序列进行排序,例如对字符串进行排序
print(sorted("geekori")) # 运行结果:['e', 'e', 'g', 'i', 'k', 'o', 'r']
x = [5,4,1,7,5]
x.sort(reverse=True) # 对列表x中的元素值降序排列
print(x) # 运行结果:[7, 5, 5, 4, 1]
5.元组
5.1.元组的创建:
a=1,
b=(1,)
c=(1,2,3)
print(a,b,c,end="")
#(1,) (1,) (1, 2, 3)
5.2.
- 将字符串和列表转换成元组:
- tuple([1,2,3]) 返回一个(1,2,3)元组
四、字符串
1.字符串基本操作
- 索引
- 切片
- 乘法
- in
- len、max、min
2.格式化字符串
2.1.三种传参方式
1.元组传参
- 在字符串a里添加 %,定义字符串模板
- 定一个元组b,里面是要传的参数值
- a%b
# 定义字符串模板
formatStr = "Hello %s. Today is %s"
# 初始化字符串模板参数值,此处必须使用元组,不能使用列表
values = ('Mike', 'Wednesday')
# 格式化字符串
print(formatStr % values)
- 显示%,打两个%%。显示$,打两个 $$
2.模板字符串Template类
- 先导入string模块中的Template类
- 在 Template() 的参数中创建模板
- 用substitute()传参
# 引用string模块中的Template类
from string import Template
template1 = Template("$s是我最喜欢的编程语言, 而且$s功能强大")
# 指定格式化参数s的值是Python
print(template1.substitute(s='Python'))
# 当格式化参数是一个字符串的一部分时,为了和字符串的其他部分区分开,
# 需要用一对大括号将格式化参数变量括起来
template2 = Template("${s}stitute")
print(template2.substitute(s='sub'))
3.字符串format()方法
- 顺序传参字符串里的大括号
- 关键字参数传参字符串里的大括号
- 在大括号里指定传参
#可以顺序赋值和关键字传参赋值
s3 = "Today is {week}, {},the {} temperature is {degree} degrees."
print(s3.format("aaaaa", 77777, degree = 22, week ="Sunday"))
#可以关键字传参赋值和指定赋值,1指定77777,0指定aaaaa
s4 = "Today is {week}, {1},the {0} temperature is {degree} degrees."
print(s4.format("aaaaa", 77777, degree = 22, week ="Sunday"))
#可以关键字传参 代换列表名
namelist = ["Bill", "Gates"]
print("Mr {name[1]}".format(name = namelist))
#还可以关键字传参 代换模块名
import math
s5 = "The {mod.__name__} module defines the value {mod.pi} for PI"
print(s5.format(mod = math))
4.fomat()方法和元组传参的类型符
类型符 | 描述 |
---|---|
a | 将字符按Unicode编码输出 |
c | 将整数解释成字符 |
d | 格式化整数 |
s | 格式化字符串 |
u | 格式化无符号整型 |
b | 格式化无符号二进制数 |
o | 格式化无符号八进制数 |
x | 格式化无符号十六进制数 |
X | 格式化无符号十六进制数(大写) |
f | 格式化浮点数,可指定小数点后的精度 |
e | 用科学计数法格式化浮点数 |
E | 作用同e,用科学计数法格式化浮点数 |
g | f和e的简写,低于等于6位是f,高于六位科学计数e |
G | F 和 E 的简写 |
p | 用十六进制数格式化变量的地址 |
% | 将数值格式化成百分比的形式 |
5.字段宽度、精度、对齐、用0填充,用符号填充
from math import *
print('{0:<010.2f}\n{0:^010.2f}\n{0:>010.2f}'.format(pi))
- 冒号前的0代表第0个元素
- 冒号后的<是向左对齐 >是向右对齐 ^是居中
- 冒号后第一个0代表用0填充
- 10代表字段长度是10
- .2代表精确到小数点后两位
from math import *
print('{0:@<10.2f}\n{0:@^10.2f}\n{0:@>10.2f}'.format(pi))
- 冒号前的0代表第0个元素
- 冒号后第一个符号@代表用@填充
- 冒号后的<是向左对齐 >是向右对齐 ^是居中
- 10代表字段长度是10
- .2代表精确到小数点后两位
3.字符串方法
方法名 | 描述 |
---|---|
center(a,b) | 返回格式化宽度为a的字符串居中,用b来填充的字符串 |
find(a,b,c) | 返回找第一次出现a的起始位置,从b位置开始到c,左闭右开,没找到返回-1 |
s.join(list) | 将字符串s添加在list列表的每个元素后面 |
s.split(a) | 用a分割字符串s,是join() 的逆方法 |
lower() upper() | 返回全部小写的字符串和全部大写的字符串 |
capwords() | 返回全部英文单词首字母大写的字符串 |
s.replace(a,b) | 将字符串s中的字符串a改为b |
s.strip(" *&") | 截掉字符串前后的" *&" |
#join的用法
list=['1','2','3','4','5']
s="*"
print (s.join)
#1*2*3*4*5
#strip的用法
print("*** &* Hello& *World**&&&".strip(" *&"))
#Hello& *World
translate方法和maketrans方法
- 用maketrans方法创建替换表
- 按照替换表用translate方法逐个替换
- makestrans第一二个参数分别代表要替换的字符串,第三个参数是要删除的字符串,全部删除
- maketrans通过字符串s来调用,返回的是一个字典
格式:
s = "I not only like python, but also like kotlin."
table= s.maketrans("ak", "$%", " ")
print(table)
print(len(table))
print(s.translate(table))
五、字典
1.创建和使用字典
1.1.定义字典
- 用键来映射值,一个字典里有唯一的键对应不同的值,键就是id
- 在大括号中定义,每个键值用逗号分隔,键与值用冒号分隔
- dict(a)函数来创建字典:返回一个由只有两个元素的列表组成的列表a转换成的字典
- 字典可以一直嵌套,所以可以多重索引
- 索引都是索的键,不是索的位置,字典里只有键,没有位置
#直接定义
d0={'Bill': '1234', 'Mike': '4321', 'Marry': '7753'}
#用dict来定义
items=[["Bill","1234"],["Mike","4321"],["Marry","7753"]]
d1=dict(items)
print(d1)
#均输出:{'Bill': '1234', 'Mike': '4321', 'Marry': '7753'}
1.2.字典的基础操作:
取值、赋值、添加键值对、计算键值对数量、查找键、删除键值对
items= {"zero":"零","one":"壹","two":"贰"} #定义
a=items["one"] #取值
print(a)
items["two"]="貳" #赋值
items["three"]="叁" #添加键值对
b=len(items) #计算键值对数量
print(b)
if "one" in items: print("\"one\" is in items")#查找键
del items["zero"] #删除键值对
print(items)
1.3.用字典格式化字符串
format_map函数将键全部换成值
2.字典方法
方法名 | 描述 |
---|---|
s.clear() | 清空字典s中所有元素 |
s.copy(a) s.deepcopy(a) | 返回浅复制和深复制的字典a |
fromkeys() | 返回用键来创建的新字典,每个键对应同样的值,第一个参数是键的序列,第二个参数是对应统一的值 |
get(key,a) | 返回键对应的值,好处是key不存在的时候会返回指定值a,不会抛出异常 |
items() | 返回字典中的所有键值对元组的列表,用于for循环结构进行迭代 |
keys() | 返回字典中的所有键的的列表,用于for循环结构进行迭代 |
value() | 返回字典中值的列表 |
pop() | 返回指定的key-value对,并删除这个键值对(索引都是索的键,不是索的位置,字典里只有键,没有位置) |
popitem() | 返回字典中最后一个key-value,并删除这个键值对 |
setdefault() | 如果键不存在就添加该键值对、如果键存在就忽略不修改,返回的是添加键值对的值,或者忽略不修改的值 |
d1.update(d2) | 用一个字典d2去更新覆盖另一个字典d1 |
- 浅复制就是第二层以下的所有层,原字典和新字典都指向同一个值。
- 深层次复制之后的字典和原字典的元素完全脱离。
六、函数
1.函数基础
1.1.
- def 函数名(参数):
- 无需指定数据类型和返回值类型
- 没有返回值的函数。输出时输出None
2.函数参数
2.1.
- 数值、字符串、bool类型的在函数里都是值传递,只在栈内有效
- 复合类型(列表、字典、对象)在函数里是引用类型,指针指向同一个位置,可以改变函数外部变量值
- 因为不用指定参数类型,所以既可以按位置传递参数,也可以按关键字赋值来传递参数:
def greet(greeting,name) :
return "问候语:"+greeting+" 姓名:"+name
print(greet(name="李宁",greeting="Hello"))
#问候语:Hello 姓名:李宁
- 关键字参数一定要在位置参数后面
- 同一个形参不能同时传位置参数和关键字参数
- 可以为参数指定默认值,指定默认值之后的参数都要有默认值
2.2.
- 可变参数:参数个数可变
- 在参数前加上一个*
- 可变参数在函数内部的表现是元组
- 可变参数后面不可以接普通参数,除非是有默认值的参数或者是关键字参数传值
2.3.将序列作为参数传入函数
- 所有参数默认都是字符串类型
- 利用可变参数的传值方式可以传入序列,将每一个序列的值作为单个参数传入
- 定义时可以加两个参数,传参时也要。没有加,那就都不
def add1(x,y,z):
return x + y + z
print(add1(1,2,3))
#6
list = [2,3,4] # 可以用列表或元组
print(add1(*list))
#9
def add2(*numbers):
result = 0
for number in numbers:
result += number
return result
print(add2(1,2,3,4,5))
print(add2(*list))
#15
#9
dict = {'x':100, 'y':200, 'z':12}
print(add1(**dict))
#321
def add3(**numbers):
result = 0
for item in numbers.items():
result += item[1]
return result
print(add3(**dict))
#312
3.作用域和递归
3.1.
- py 局部的变量需要在使用前赋值
- 函数的作用域是一步一步向上级取值的
3.2. 阶乘和斐波那契数列
def jc(n):
if n == 0 or n == 1:
return 1
else:
return n * jc(n - 1)
print(jc(10))
def fibonacci(n):
if n == 1:
return 0
elif n == 2:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10))
七、类和对象
1.创建类、添加私有方法
- class 类名:
- 第一个参数self 代表当前类的实例,可以用self来引用类里面的实例(self 可以是所有的变量名来代表,这里用self只是一种习惯)
- 类的成员变量都用(self.)来定义和调用
- 创建对象时没有new,其他都和java一样
- 类时空的时候,pass,而且要缩进
私有方法private在py里:
- 方法名前加双下画线_ _
- 原理是其方法名改名改成了 _类名_方法名()
class MyClass: #定义类
def getName(self):
return self.name
def setName(self, name):
self.name = name
self.__outName()
def __outName(self):
print("Name = {}".format(self.name))
myClass = MyClass() #创建对象
import inspect #导入inspect模块,求出一个类里的所有方法名
methods = inspect.getmembers\
(myClass, predicate=inspect.ismethod)
for method in methods:
print(method[0])
print("------------")
myClass.setName("Bill")
print(myClass.getName())
myClass._MyClass__outName() #使用myclass对象中的方法实例
#print(myClass.__outName())
输出结果:所以该类中已经不存在outname()方法,改名为了_MyClass__outName()方法
2.如何继承一个或多个类
- class 子类名(父类名,父类名,父类名):
- 方法同名的话,写在前面的父类会覆盖写在后面的父类,不会重载,只看方法名,不看参数个数
- py没有接口,可以用hasattr(a,b)函数和gatattr(a,b,c)函数检测对象a中是否有方法b
class MyClass:
def method1(self):
print("method1")
my = MyClass()
if hasattr(my, 'method1'):
my.method1() #method1
else:
print("method1方法不存在")
def sum():
return 1+2+3+4
method = getattr(my, 'method2',sum)
print(method()) #10
3.如何检测类之间的继承关系
3.1.
- issubclass函数,第一个参数是子类,第二个参数是祖先类
- 若有继承关系,返回True,若没有,返回Falese
- __(都是双下画线)。 __bases__函数返回该类的直接父类
- 所有类都是object类的子类
- isinstence(a,b)函数,判断对象a是不是类b的实例
- 第一个参数是对象,第二个参数是类
class YeYe:
def f1(self):
return 50
class BaBa(YeYe):
def f2(self):
print("f2")
class ErZi(BaBa):
def f3(self):
print("f3")
class MoshengRen:
def method(self):
return 40
print(issubclass(ErZi, YeYe)) #T
print(issubclass(ErZi, BaBa)) #T
print(issubclass(ErZi, MoshengRen)) #F
print(ErZi.__bases__)#Ba
print(BaBa.__bases__)#Ye
Sunlight = ErZi()
print(isinstance(Sunlight, ErZi))#T
print(isinstance(Sunlight, BaBa))#T
print(isinstance(Sunlight, YeYe))#T
print(isinstance(Sunlight, MoshengRen))#F
八、异常
1.抛出异常
- raise 抛出异常
- class 异常类名(Exception):来自定义异常类
class WarpdriveOverloadException(Exception):
pass
warpSpeed = 12
if warpSpeed >= 10:
raise WarpdriveOverloadException\
("曲速引擎已经过载,请停止或弹出曲速核心,否则飞船将会爆炸")
2.捕捉异常
- 先运行try里面的代码,若遇到异常,直接goto到except语句运行
x = None
while True:
try:
if x == None:
x = int(input("请输入分子:"))
y = int(input("请输入分母:"))
print("x / y = {}".format(x / y))
break;
except :
print("分母不能为0,请重新输入分母!")
- 捕捉多个异常,先写出各个异常的抛出情况,再在try语句中实现功能。最后写出多个(except Exception:)语句就可以了
- 可以在except后面写多个异常,就可以同时处理多个异常
- except Exception as e : 抛出异常对象e
- finally语句中的语句一定会被执行
class NegativeException(Exception):
pass
class ZeroException(Exception):
pass
class SpecialCalc:
def add(self,x,y):
if x < 0 or y < 0:
raise NegativeException
return x + y
def sub(self,x,y):
if x - y < 0:
raise NegativeException
return x - y
def mul(self,x,y):
if x == 0 or y == 0:
raise ZeroException
return x * y
def div(self,x,y):
return x / y
while True:
try:
calc = SpecialCalc()
expr = input("请输入要计算的表达式,例如,add(1,2):")
if expr == ":exit":
break;
result = eval('calc.' + expr)
print("计算结果:{:.2f}".format(result))
except NegativeException:
print("******负数异常******")
except ZeroException:
print("******操作数为0异常******")
except ZeroDivisionError:
print("******分母不能为0******")
except:
print("******其他异常******")
3.异常、函数、栈跟踪
- 如果最里层的函数抛出一个异常,而且没有得到处理,则这个异常会一直进行传播,直到传播到顶层函数,并让程序中断
九、方法、属性和迭代器
1.构造方法
- def init(self,a):
- 构造方法的方法名就是init,前后各加两个下画线__init__
- 子类对父类方法的重写,直接覆盖父类方法
- 只能在构造方法中使用self创建类的成员变量,除非都是静态变量
1.2.super函数调用父类的方法
- super(SongBird,self).init(hungry)
- 第一个参数代表类名,若继承父类的方法,不写参数。若继承爷爷类的,则参数写爸爸类的类名
- 第二个参数是self,表示当前的实例
- 之后再用(.)接 调用的什么方法
class Animal:
def __init__(self):
print("Animal init")
class Bird(Animal):
def __init__(self, hungry):
super().__init__()
self.hungry= hungry
def eat(self):
if self.hungry:
print("已经吃了虫子!")
self.hungry = False
else:
print("已经吃过饭了,不饿了!")
b = Bird(False)
b.eat()
b.eat()
class SongBird(Bird):
def __init__(self,hungry):
super(SongBird,self).__init__(hungry)
self.sound = '向天再借五百年'
def sing(self):
print(self.sound)
sb = SongBird(True)
sb.sing()
sb.eat()
2.属性
2.1.属性就是成员变量
- __dict__是系统内置的成员变量,用于保存对象中所有属性的值
- 使用:self. dict[成员变量名]=值
2.2.监控对象中的属性:
- getattr(self,name)方法 监控所有的属性的读操作
- setattr(self,name)方法 监控所有的属性的写操作
- delattr(self,name)方法 监控所有的属性的删除操作
这些特殊方法都是自动调用
3.静态方法、类方法
- 静态方法的调用不需要创建实例,和函数差不多,定义也和函数一样,只需在前添加一个装饰器 @staticmethod
- 在实例方法中可以调用类方法和静态方法,反之则不行
class MyClass:
name = "Bill"
def __init__(self):
print("MyClass的构造方法被调用")
self.value = 20
@staticmethod
def run():
print(MyClass.name)
print("MyClass的静态方法run被调用")
@classmethod
# 这里self是元数据
def do(self):
print(self)
print(self.name)
print('调用静态方法run')
self.run()
# 如果是类方法,就无法访问self中的成员变量了
#print(self.value)
print("成员方法do被调用")
def do1(self):
print(self.value)
print(self.name)
print(self)
MyClass.run() #调用静态方法
print('----------------')
c = MyClass() #调用构造方法
print('----------------')
MyClass.do() #c.do() 调用类方法
print('----------------')
c.do1() #调用成员方法
4.迭代器、生成器
- 为了节省内存资源,迭代器和生成器从数据源中一个个获取数据,前者以类作为载体,后者以函数作为载体
- 迭代器:iter()方法,返回对象本身
- next()方法,调用下一个迭代对象
- 生成器:用yield来返回值
#可无限次迭代直角三角形的行的迭代器
class RightTriangle:
def __init__(self):
self.n=1 #定义一个变量n,表示当前的行数
def __next__(self):#通过字符串的乘法获取每一行的字符串
result='*' * (2*self.n - 1)
self.n += 1
return result
def __iter__(self):
return self #该方法必须返回一个迭代器
rt=RightTriangle()
for i in rt : #对迭代器进行迭代
if len(i) > 20: #控制输出的范围,否则会无限迭代
break;
print(i)
# 递归生成器
def enumList(nestedList):
try:
for subList in nestedList:
for element in enumList(subList):
yield element
except TypeError:
yield nestedList
nestedList = [4,[1,2,[3,5,6]],[4,3,[1,2,[4,5]],2],[1,2,4,5,7]]
for num in enumList(nestedList):
print(num, end=' ')