- 编程语言:编程语言是控制可以直接或者间接控制计算机来执行任务的字码。
- c /c#/c++/java/lua/python/Shell/go…
python简介:
- python是最近比较受欢迎的编程语言
- 是一种解释性的语言,一边编译,一遍执行。解释器有CPython(官方),Jpython(可以运行在java 平台上),IronPython(可以运行在.NET和Mono平台),PyPy(Python实现的,支持JIT即时编译)
- 优点:简单,易学,免费,开源,高层语言(不需要关注底层语言),可移植性,面向对象,可扩展性,丰富的库,规范的代码(优雅)
- 缺点:运行效率慢,解释性语言共有的
可以做很多事情:web应用开发,桌面软件,科学计算,爬虫,游戏,出产品原型。。。
编辑工具:Pycharm
python2和python3的区别
- 编码环境不一样,python2:ascii, python:utf-8
- import方式不一样,python2:绝对路径和相对路径;python3:绝对
- 类的定义:python2:老式类和新式类;python3:新式类
- 浮点数除法操作符:python2:/整数除法,//小数除法;python3,相反
- …
注释
- ”,”“,”’ ”’,”“”“”“
变量
- 存储数据的篮子,实际上是一个地址引用,Python中一切皆对象,而对象名实际上都是对真实存储地址的引用
- python的常规变量类型:数字(int,float,long,complix),string,bool,列表,字典,元组
- type(),查看变量的类型
标示符
- 自定义的有意义的字码/字码串,如变量名,类名,方法名等
- 规则:1.字母数字下划线 2.首个字符不能是数字 3.不能是关键字(内置标示符)4.见名知义 5.驼峰法:类名:ClassName 变量名和方法名:var_1 fun_1
- 输出内容到控制台
- print (“内容”)
print(”%格式符号”%内容)
- %c
- %s
- %d
- %u无符号10进制数
- %o:八进制整数
- %x:16进制整数(小写字母0x)
- %X:16进制整数(大写字母0X)
- %f:浮点
- %e/%E:科学计数法
\n :换行输出
输入
- 程序停止,等待输入内容并且按下enter键后,将输出的内容记录下来,字符串类型
- python2:raw_input(“提示的内容”)
- python3:input(“提示语句”)
运算符
- 变量间相互作用的符号
- / :python2:整数除 ;python3:小数除
- //: 地板除,获取<=当前实际值的最近的整数值
- **: 指数,2**2 == 4;2**3=8
数据类型转换
- 将一种数据类型的数据转换为另外一种类型的数据
- complex(real,[,imag]): 创建一个复数,实部为real,虚部为imag
- str():将对象转换为字符串,给人看的
- repr():将对象转化为字符串,给程序员看的,更强大
- chr():将一个整数转换为unicode字符
- ord():显示一个字符的ASCII排序数字
- hex():将一个整数转换为16进制
- oct():将一个整数转换为8进制
- bin():将一个整数转化为2进制
判断
- yes/no ,yes怎样,no 怎样。。。
if :
if 条件:
代码- 一个条件,满足条件,执行;钥匙开门,能打开进入
if 条件:
代码
else:
代码一个条件,两个结果;钥匙开门,能打开,进入,不能打开,去姥姥家
if 条件:
代码
elif 条件:
代码
elif 条件:
代码
else:
代码- n条件,n+1个结果;如果能打开门,进入,如果身上有钱,去吃外卖,如果心情好,去跳舞,否则,就在门口等着老妈回来
用于条件判断的运算符:用于判断,返回True/False的结果
- 关系运算符:==,!=。。。
- 逻辑运算符:and, or, not
循环:重复执行
- while ,for
while 条件:
代码
判断条件是否满足,满足就执行代码,执行完一轮,再次判断条件,满足继续执行,执行完再判断。直到判断不满足,跳出循环,执行下面的语句
- 例子:给女朋友说10000遍对不起
i=0
while i < 10000:
print("对不起")
i+=1
- 好处,精炼代码,提高代码的复用型。美观。需要多次重复的代码都可以使用循环语句
for 循环
- 用来遍历一个可迭代对象的方法
for i in [ilter]:
代码块
iter中的元素从前到后依次取出,代码里可以使用,也可以不使用,执行完代码,再取第二个,再执行代码,再取第三个,直到将iter中的最后一个元素取出来,执行完了代码块,跳出循环,执行for语句结构后的代码
- break:立即跳出当前循环,执行当前循环代码结构后的代码
- continue:立即结束当轮循环,进行循环语句的条件判断(while)/取ilter的下一个元素(for)
- break/continue 只能在循环语句中使用,不能单独使用
- break/continue 只能在使用在嵌套语句的时候,只能对被嵌套的最近的一层循环结构起作用
字符串
- 双引号/单引号中的数据就是字符串
”, “”,”’ ”’ ,”“” “”“,四种定义字符串的形式
字符串输出,占位符
- 字符串输入,python3:input(), python2:raw_input();()里为提示字符
- 下标
- 从0开始数
- 切片[起始位置(包括):结束位置(不包括) : 步长(一次跳几个字符)]
- 其中起始位置和结束位置如果是正数代表第当前第 数字+1 个字符,0 代表第 个字符,负数代表从最后往前数第几个,-1代表倒数第一个
- 步长不写代表1,负数代表从后往前逆序截取字符
- 反转字符串 :[::-1]
- 常见的字符串操作
- str.find(“字符”)查看是否有“字符”,有返回索引值,没有返回-1
- str.index():和find()一样,只是,如果没有找到不是返回-1,而是报异常
- str.count(str1,a(开始索引值),b(从索引值开始的长度)):返回str1在str中从索引为a到之后的长度为b的字符串片段中出现的次数,没有出现过,返回 0
- str.replace(str1,str2,num):将str1替换为str2 num次
- str.split(str=”“, num):将str以”“,分隔num次,若没有参数,则是对str中的所有空白字符进行分隔,返回列表
- str.capitalize():将str首字母大写
- str.title():将str的每一个单词的首字母大写
- str.startwith(“str1”):若str是以str1开头的,返回True,否则返回False
- str.endwith(“str2”):若str是以str2结束,如果是返回True,否则返回False
- str.lower():str中的所有大写字符转换为小写
- str.upper():str中的所有小写字母转换为大写
- str.rjust(width):返回str字符串的右对齐至长度为width的新字符串,不足空格填充
- str.center(width):返回str字符串居中至长度为width的新字符串,不足以空格填充
- str.lstrip():删除str左边的空白字符串
- str.rstrip():删除 str右边的空白字符串
- str.strip():删除str字符串两边的空白字符串
- str.rfind():类似于find()函数,不过从右边开始查找
- str.rindex():类似于index(),不过是从右边开始
- str.partition(str1):把str以第一个出现的str1分割成三部分,str1,前,str1,后
- str.rpartition(str1):把str以第一个出现的str1分隔成三部分,str1前,str1, 后,不过是从右边开始找
- str.splitlines():按照行分隔,返回一个包含各行作为元素的列表
- str.isalpha():如果str所有的字符都是字母,则返回True,否则返回False
- str.isdigit():如果str所有的字符都是数字,则返回True,否则返回Flase
- str.isalnum():如果str所有的字符都是字母或者数字,则返回True,否则返回False
- str.isspace():如果str所有的字符都是空格,则返回True,否则返回False
- str.join(列表):列表中的每一个元素后面插入str,构造出一个新的字符串
列表
- 可以盛放各种数据类型的容器
- a = [1,2,3,”a”,”b”,”c”,{“name”:”michael”}]
性质:
- 有下标,可以利用下标索引列表中的每一个值:name = a[6][“name”]
- 可以被for遍历
相关操作:增删改查
- 增:
- list.append(元素):在列表的最后面添加元素,一次只能添加一个,如a.append(3)
- list.extend(list1):在list中依次添加list1中的每一个元素,如a.extend([3,4,5])
- list.insert(index_num,元素):在list的索引值为index_num的地方添加元素,如a.insert(1,88)
- 删:del,pop,remove
- del list[index_num]:删除list中索引值为index_num的元素,如,del a[0]
- list.remove(“元素”):删除list中的”元素“,如,a.remove(88)
list.pop(a):删除list中索引值为a的元素,不加参数,删除最后一个,如,a.pop()
改:
a[‘index_num’] = value,如 a[2] = 22
查:
- in, not in , index, count
- a in list :判断a是否在list中,在,返回true,否则返回False
- a not in list :判断a 是否不在list中,是,返回true,不是,返回False
- a.index(value, a,b):获取value在a中的下标 ,a,b表示在下标[a,b)索引区间内寻找,有,返回索引值,没有,报错。和字符串的index()用法相同,如,a.index(‘a’,1,10)
- 其实字符串就是一个列表
- a.count(‘a’):列表a中,获取‘a’在列表中出现的次数
注意和字符串中的用法不一样,字符串中,str.count(‘a’,a,b),a,b代表索引区间[a,b),列表中没有这两个参数
列表可以嵌套:l1 = [[1,2,3],[4,5,6]], 查询出6:li[1][2]
元组
- (1,”a”,{“name”:”michael”})
- 可以理解成不能修改的列表(不能增,删,改)
字典
- 存储key:value键值对的数据结构,可以根据有意义的key值,获取自己记不住的vlaue,像字典一样,key就是前面的索引,value对应是某个索引字的详解
- dict = {“name”:”michael”,”age”:18}
操作,增删改查
- 增: dict[“没有的key”] = value
- 删: del dict[‘key’] dict.clear():清空字典内容为空字典
- 改:dict[‘已有的key’] = new_value
- 查:dict[key] ;
- len(dict):查看dict 的键值对的个数,返回个数
- dict.keys():获取字典的所有key,返回列表对象,可遍历获取元素
- dict.values():获取字典大的所有value返回列表对象,可遍历获取元素
dict.items():获取字典的所有键值对,每个键值对放在一个元组里,组成列表对象返回,可遍历使用
?实现带下标索引的遍历
- 就是遍历后输出的结果前面带索引值–加一个 计数器 从0开始计数,输出的时候带着这个计数器的值就可以了。
a = ["a","b","c"]
i = 0
for x in a :
print("%d,%s" % (i, x))
i+=1
- 以上功能用一个 内置的enumerate()函数,就可以解决了
a = ["a","b","c"]
for index, i in enumerate(a) :
print("%d,%s" % (index, i))
公共方法
- +,列表,元组,字符串;字典不可以,因为字典的key不能重复
- *, 列表,元组,字符串;字段不可以,因为字典的key不能重复
- in ,not in :列表,元组,字符串, 字典
python 内置函数
- cmp(a,b):比较a,b的小,a>b,返回1;a
总结
- 数据类型:数字(int,long, float,complex),bool, str,list,dict,turple
- 执行流程
- 选择:if;if else;if elif
- 循环:for;while
函数
- 为了完成一个功能,将一行或者多行代码封装成一个可以调用,返回执行结果的结构。
- 格式
# 定义
def 函数名(形参)
代码
return 返回值
# 调用
result = 函数名(实参)
四种函数类型:
- 无参数,无返回值:花钱
- 无参数,有返回值:不给钱,给我带一份外卖
- 有参数,无返回值:给你钱花,随便花不用给我什么
- 有参数,有返回值:给你10块钱,给我带一份外卖
函数嵌套使用:函数里面前套函数
- 函数执行完是返回到调用它的地方
求三个数的平均值,调用函数完成
def avg(a, b, c):
result = (a + b + c) / 3
return result
result = avg(1, 2, 3)
print(result)
局部变量
- 在函数内定义的变量
- 其作用范围是只在定义它的内部,出了函数就不能用了
全局变量
- 在函数外定义的变量
- 一个函数里可以用,另一个函数里也可以用
- 如果想要在函数里修改全局变量,需要 用 global声明一下
- 若遇到全局变量和局部变量同名的情况,函数里局部变量优先级大于全局变量
函数之间传递数据的方式
- 全局变量
- 传参
- 函数嵌套
返回值2
- 遇到return就会返回函数的执行结果
- return 后面跟上列表,字典,元组等可以存储多个数据的结构,就可以一次性返回多个值
- 如果函数直接跟多个值,默认返回元组
参数2
- 缺省参数:def test(age=1),如果传入参数,参数实际值等于传入的值,如果不传入参数,就会默认age=1
- 注意缺省参数一定要位于参数列表的最后面,否则会报错
不定长参数
- 需要处理不确定个数的参数的时候使用的参数形式
- *args(元组),**kwargs(字典)
- 如果同时有缺省参数,和两种不定长参数,它们的顺序应该是:(*args,a=5,b=6,**kwargs)
拆包
- 对于函数return的多个值的包一次性拆开,用多个变量接收
# 对元组进行拆包
def test()
return 1,2
a,b = test()
# 字典和列表的拆包形式和元组相同
# 注意字典拆包获取的是key值
- 交换两个变量的值:
a,b=b,a
引用
- python中,变量名,类名,函数名,其实都只是对实际存储的数据和代码的存储单元的地址码的一个指向。这种指向就叫引用。
- python值的传递,就是引用的传递
- 可以用id(名字)来判断引用的内存地址是否相同,来判定是否引用的是同一个数据
可变/不可变类型
- 可变/不可变类型,都是指的数据类型
- 不可变类型是值数据是一个整体,不能对已经赋值的数据进行增删改的操作的数据类型
- 不可变类型包括 数字,布尔,字符串,元组
- 如果想要改变不可变类型变量的值,只有从新赋值,也就是变量需要重新引用一个新的内存地址码
- 可变类型是可以对已经定义赋值的数据进行更改操作(增/删/改)的数据类型
可变类型包括:字典,列表,集合
可变类型变量作为参数传递,对变量进行更改,会改变原变量的值
- 不可变类型作为参数传递,对变量进行更改(也只能重新赋值),不会改变原变量的值,因为函数内更改的变量值,实际上是重新引用了一块新的内存地址,但是如果声明是全局变量了,那么全局变量的值就会改变了
a = 100
b = []
def test(a):
a = 200
def test1():
global a
a = 200
def test2(b)
b.append(2)
test(a)
a
100
test1()
a
200
test2(b)
b
[2]
函数使用注意事项
- 函数名不要重复
- 调用函数传参的时候,注意实参和形参的顺序要一致
- 如果函数有返回值,那么就应该定义一个变量来接收
递归函数
- 函数的内部调用这个函数本身
关键点:函数在哪里调用,返回值就回到哪里
示例 1.使用递归函数计算10!
# 使用递归函数,计算10!
# 关键点,函数嵌套函数本身,函数在哪里调用,结果就返回到哪里
def diguiFun(a):
if a > 1:
result = a * diguiFun(a - 1)
else:
result = 1
return result
if __name__ == '__main__':
result = diguiFun(10)
print(result)
匿名函数
- lambda函数,可以当做变量使用的函数
- 格式
lambda 参数:表达式
- 使用方法:用一个变量定义表达式,像使用函数一样给变量传值(传值的数量,格式要和lambda表达式的参数数量,格式一致),返回表达式计算的结果
a = lambda i:i+1
print(a(3))
- 特点是小而灵活,一般简单的计算,使用lambda表达式
- 使用场景
- 简单的计算,不用定义标准函数了,一行搞定
- 匿名函数(lambda表达式)可以当做参数传递给函数
lamb = lambda a,b:a*b
def test_lamb(lamb):
print(lamb(2,3))
test_lamb(lamb)
6
- 作为内置函数的参数
一个列表
stus = [
{"name": "zhangsan", "age": 18},
{"name": "lisi", "age": 19},
{"name": "wangwu", "age": 17}
]
#1.按照名字给列表stus排序
stus.sort(key=lambda i:i["name"])
stus
[{'name': 'lisi', 'age': 19}, {'name': 'wangwu', 'age': 17}, {'name': 'zhangsan', 'age': 18}]
#2.按照年龄给列表stus排序
stus.sort(key=lambda i:i["age"])
stus
[{'name': 'wangwu', 'age': 17}, {'name': 'zhangsan', 'age': 18}, {'name': 'lisi', 'age': 19}]
给程序传参
- 给 sys模块的argv列表传参
- 步骤
- 在.py文件中导入sys模块
- 在终端运行该.py文件,在文件名后面加上要传的参数
test.py:
import sys
print(sys.argv)
终端:
python3 test.py 1 2
['test.py', 'q'. '2']
特点,argv列表的第一个元素永远是文件名
作用:一步到位,不用一个个传入
应用场景:当你不想要一个个传参数的时候,就使用给程序文件传参的方式一次性把文件需要使用的参数传完
列表推导式
- 快速生成一个列表的方式
- 基本格式
[x for x in range(10)]
如:
[x for x in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- 多个 for 循环
[(x, y, z) for x in range(2) for y in range(2) for z in range(2)]
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
# for 循环的嵌套
- 添加条件判断
[x for x in range(10) if x > 5 ]
[6, 7, 8, 9]
- 练习
请写出一段 Python 代码实现分组一个 list 里面的元素,比如 [1,2,3,...100]变成 [[1,2,3],[4,5,6]....]
# 思路:
# 1.三个一组,切片 ;2.切片的起点(index),0,3,6...;3.用range(0,100,3)获取这些切片下标的起点 4.获取片的起始下标位置x,那么新列表的每个元素就应该是[1,2,3..100][x:x+3]
# 代码
a = [i for i in range(1,101)]
res = [a[x:x+3] for x in range(0,101,3)]
集合
- {a,b,c}
特点:
- 无序,没有下标
- 不能有重复的元素
作用
- 用来对数据的去重
a_before = [1,2,3,4,4,4,3,2,3,4,5,5]
a_set = set(a)
a_set
{1, 2, 3, 4, 5}
a_after = list(a_set)
a_after
[1,2,3,4,5]
列表,集合,元组之间的转换
- 列表,集合,元组之间可以相互转换
- list(tuple/set):将元组或者集合转换为列表返回
- tuple(list/tuple):将列表或者集合转换为元组返回
- set(list/tuple):将列表或者元组转换为集合返回
文件操作
- 文件数据的集合体
- 文件的格式
- 系统,程序,配置文件:.iso, .dll, .py, .pyc, .sql,
- 文本:.txt, .pages
- 图片:.image, .png, .gif, .ps, .mpeg
- 音频:.mp3
- 视频: .avi, .mp4, .rmvb, .3gp, .mov
- 其他:.html, .xml, .json
- ……
- 实际上计算机底层只人0,1,所有数据类型都是0,1的组合,进行不同的排序
- 文件类型是给人看的,对于程序员来说,文件类型是可以自定义的,一个后缀而已
- 使用文件的目的是为了重复利用一段数据集
- 使用不同格式的数据的目的是区分不同类型的数据,虽然本质上都是0,1,但是不可能所有的数据都用0,1表示,无法操作。分成不同类型的数据,易于不同数据的归类,对一类数据有一种处理方法,不同的数据处理方法不一致
文件操作
- 打开/新建文件,读写, 关闭
- 打开
file = open (file, 'w' )
:以写的方式打开file - 读写
file.write("内容")
:往打开的file文件中写入’内容’
- 关闭
file.close()
:将 file文件关闭
- 关闭
打开,读写,关闭是标准步骤,一定不要忘了关闭文件,忘了关闭,一直打开,会占用系统资源
不想写file.close()可以用以下结构打开文件
with open(file, 'w') as f
f.write('内容')
文件file 写完毕后会自动关闭
- 打开方式
- r:只读模式
- w:只写,覆盖
- a:只写,追加
- rb:以二进制格式打开,只读
- wb:以二进制格式打开,只写,覆盖
- ab:以二进制格式打开,只写,追加
- r+:读写,文件指针会放在开头
- w+:读写,覆盖
- a+:读写,追加
- rb+:ab+:以二进制打开,读写
- wb+:以二进制打开,读写,覆盖
- ab+:以二进制打开,读写,追加
- 默认为 r 模式
读取数据
- read() :读取全部内容,返回
- read(num):读取Num个字符
- readlines():读取全部内容,按照一个一个元素,返回一个列表
- readline():每次读取一行,返回,再次读取,会继续读取下一行
文件的相关操作
- 对文件的一些操作:重命名,删除文件,创建文件夹,获取当前目录,改变默认目录,获取目录列表,删除文件夹
- 需要导入 os 模块:
import os
- 文件重命名:
os.rename(old_file_name, new_file_name)
- 删除文件:
os.remove(file)
- 创建文件夹:
os.mkdir("文件夹名")
- 获取当前目录:
os.getcwd()
- 改变默认目录:
os.chdir('新的路径')
- 获取目录列表:
os.listdir('目录路径')
删除文件夹:
os.rmdir('文件夹路径')
*注意,如果既有对文件整体的操作,又有文件内容的操作,导入os模块时,不能使用
from os import *
,这样导入对文件整体的操作是省略了os.,方便了一些,但是打开文件的操作就会报错。
面向对象编程
- 面向过程和面向对象
- 早上起来穿衣服,自己一件一件穿–面向过程,保姆帮着穿,不用自己动手–面向对象
- 面向对象和面向过程都是程序中解决实际生产问题的编程思想
- 面向过程偏向于一步一步,从前到后自己做
- 面向过程是交给他方去做,自己这边获取到返回结果即可
面向对象是基于面向过程的
面向对象的思想
- 封装
- 继承
- 多态
类和对象
类
- 类:有着相同性质,能力的一类事务的抽象化集合
- 对象:一种类的一个实体
例子:百灵鸟,类,一只在树上唱歌的百灵鸟,对象
类的构成
- 类名
- 属性:静态数据
方法 :动态能力
定义类
class 类名(父类):
方法列表
# 属性也是用方法来完成定义的(__init__())
性质
- 类采用大驼峰名命名法(BigDog)
- object 是所有父类的顶级父类
- 经典类:class 类名 ; class 类名()
实例化对象
- 格式:
对象名 = 类名()
- 格式:
__init__(self)
- 用来初始化类的实例对象属性的魔法方法
- 会在实例化对象的时候自动调用
- self代表实例化对象本身
可以在实例化对象的时候传参数给实例化的对象设置特殊的属性
__str__(self)
- 如果类中没有定义__str__()方法,print(对象)会打印对象的内存地址
- 如果类中定义了__str__()方法,print(对象)会打印__str__()里return的内容
- __str__(),通常会返回这个对象的描述信息
__del__(self)
- 删除对象,python解释器默认调用的魔法方法
- 当有变量保存了一个对象的引用时,此对象的引用次数会+1
- 当解释器调用__del__()方法一次,会减少一次对象的引用次数,当对象的引用次数=0时,对象才会真正被删除,即对象占的内存会被回收
继承
- 子类可以使用父类的方法和属性
格式
class A(B),B即为A的父类,A的实例化对象可以调用B的属性和方法
继承种类
- 单继承:只继承一个父类
- 多继承:继承多个父类
多层继承 :A继承自父类B,B又继承自其父类C,那么A就是多层继承的类
多继承
- 多继承可以继承多个父类,会继承多个父类的所有属性和方法
- 如果多个父类有相同的属性和方法,默认使用第一个父类的属性和方法(会自动调用魔法方法__mro__()来给所有的父类查找顺序排序)
父类们不重名的方法和属性,子类使用不收影响
子类重写父类方法或者属性
当子类定义了和父类同名的方法或者属性的时候,调用时,会使用子类新定义的,即子类重写了父类的方法或属性
子类调用父类同名的属性或者方法
- 虽然重写了父类的属性或者方法,但是还想调用父类的属性或者方法
- 调用父类同名属性,需要调用了父类的__init__()方法:
父类名.__init__(self)
- 调用父类的同名方法,需要调用父类的响应方法:
父类名.同名方法名(self)
self 代表子类示例对象本身
super()方法的使用
- 根据mro模仿方法的顺序,调用第一个可用的父类的响应方法,或属性
- 调用格式
super().__init__()';super().方法名()
封装
- 将相同/类似的功能代码/将能够完成一个特定功能的所有代码,聚合在一起的过程
- 定义类,实例化对象使用类定义的方法,属性,就是封装的思想
私有权限
- 限制示例对象对类对象中的某些属性/方法的访问
- 格式:在定义类的过程中,在想要设置为私有权限的属性/方法名前加__(两个下划线)
- 设置为私有权限的属性或者方法,类对象可以正常访问,实例对象不能访问
- 实际上,私有权限的属性和方法就是解释器自动改了属性名/方法名而已
- 示例对象要修改私有属性的值,推荐使用间接的调用方法的形式修改。需要修改私有属性的值,需要事先在定义类的时候,定义好修改私有属性的方法,然后实例对象,调用响应方法,来完成对设置了私有权限的私有属性的修改
多态
- 定义时的类型和运行时的类型不一样,就是多态的思想
- 多个子类重写了父类的某个方法,现需要使用父类这个类的示例对象,并且需要调用这个方法。那么给他子类的相关对象调用子类的重写的方法也是可行的。
- 好处时,调用一个同名方法,完成不同的功能
- 举例子:父类,狗 ,方法:叫 (汪汪);子类:狼狗,方法:叫(汪汪汪);子类:泰迪,方法:叫(哇哇哇)。当需要调用父类狗的叫方法的时候,调用狼狗的叫和泰迪的叫也是可以的,达到了,调用同一个方法,完成不同效果的效果
类属性,实例属性
- 类对象:定义类的时候会自动生成一个类对象;示例对象:实例化类,即生成一个实例对象
- 类属性,在类对象里定义的属性,即在定义类的代码里定义的属性
- 类对象和所有实例化对象都可以使用,公用的
- 如果不想公用,可以将类属性数值为私有属性
__属性
- 实例属性,在实例化对象里定义的属性
- 只能在定义它的实例对象里可以使用
静态方法和类方法
静态方法
- 在类中定义的,使用装饰器
@staticmethod
装饰的方法 - 类对象和实例对象都可以调用
- 定义的时候不需要参数self,
def static_method()
- 定义的时候不需要参数self,
- 在类中定义的,使用装饰器
类方法
- 在类中定义的,使用装饰器
@classmethod
装饰的方法 - 第一个参数必须是类对象
cls
类对象和实例对象都可以调用
类方法和静态方法的区别
- 因为类方法的第一个参数是
cls
,通过cls
可以直接引用类对象的属性和方法 - 静态方法没有额外的参数,因此在静态方法中想要引用类对象的属性和方法,必须通过类对象来引用
- 区别就是
cls
参数,类方法有cls
,可以通过这个内置参数直接调用类对象的所有属性和方法,静态方法没有。静态方法的好处是没有参数。
- 在类中定义的,使用装饰器
__new__()
- 在实例化对象的时候,自动调用的,用来生成实例对象的魔法方法
- 至少有一个参数
cls
代表要示例化的类 ,用来实例化实例对象 - 重写此方法的时候,必须return一个实例对象示例,可以
object.__new__(cls)
,也可以是其他父类父类名.__new__(cls)
- __init__(self),这个self,就是__new__(cls),实例化的实例对象
- 也就是在实例化实例对象的时候,系统是先调用的__new__(cls),实例化了一个实例对象,然后在将这个实例对象通过self参数传给__init__(self),方法,完成实例对象的初始化(属性的设置)
- 比喻:要生产小布娃娃,__new__(cls):是原材料准备,__init__(self),是使小娃娃基本成型
单例模式
- 确保一个类只能同时攒在一个实例的模式
- 使用场景:任务管理器;回收站
- 方式:在类中重写__new__(cls)方法,使得第一次实例化的时候可以实例化成功,第二次及以后实例化的时候都直接返回第一次实例化的对象。
- 单例模式只会执行一次__init__(self)方法。
- 代码
class DanLi(object):
__instanse = None
def __new__(cls, *args, **kwargs):
if cls.__instanse == None:
cls.__instanse == object.__new__(cls)
else:
return cls.__instanse
danli = DanLi()
print(id(danli))
danli2 = DanLi()
print(id(danli2))
结果:
4305004560
4305004560
- 其他开发模式
- 工厂方法模式
- 模板方法模式
- 中介者模式
- 装饰模式
- 迭代器模式
- 解释器模式
- 桥梁模式
- 。。。。。。
异常
- 程序报错
- 捕获异常
- 检测一段代码,如果代码在运行过程中出现异常,就捕获它并作处理
- 格式
try:
一段代码
except 错误集:
处理代码
except后没有错误集,就是捕获所有异常,因为不同错误处理方式不同,一般会精准捕捉错误类型,进行对症下药,常见的错误类型有(IOError,NameError,Exception…)
捕获多个异常
- 在except后写多个错误集,放在元组里:
except (IOError, NameError)
- 在except后写多个错误集,放在元组里:
捕获异常的信息描述
- 在异常集后 用一个变量接收异常信息:
except IOError as result
- 这样result就存储了错误信息,可以使用,比如,打印出来
print result
- 在异常集后 用一个变量接收异常信息:
else
- 如果没有捕获到异常,就执行 else 里的代码
- 格式
try:
被监控的代码
except:
有异常执行的代码
else:
没有异常执行的代码
- finally
- 无论有没有异常,都要执行
- 使用场景:文件关闭,释放锁,将数据库链接返还给链接池等
- 格式:
try:
被监控的代码块
except:
有异常,执行的代码
else:
没有异常执行的代码
finally:
无论有没有异常都要执行的代码
异常的传递
- try 的嵌套
- 内部的try没有处理,会抛给外面一层的try,还没处理(没有except语句),继续抛给外面,都不处理,系统处理,正如我们没有使用try语句,出现异常时看到的那样
- 一旦try处理了,就不外抛了
抛出自定义的异常
- 自定义异常,自定义一个异常的类就行了。比如长度>3时就抛出自定义的异常类实例对象
- 抛:
raise 自定义异常实例对象
抛出后可以使用try 自己捕捉自己处理,也可以不处理,抛给外层try或者系统
异常处理中抛出异常
- 在处理异常过程中,设置一个开关switch,if 判断,需要处理的时候,自己处理,不需要自己处理的时候,再抛出
raise
模块
工具包,集成了可以完成某个或者某些功能的代码集。相当于C的头文件/java的包
模块的导入
- 1.一般导入方式:
import 模块名
- 使用模块中的函数:
模块名.函数名
- 2.当只需要模块的部分功能时:from 模块名 import 类名/函数名/变量名,…,…,
- 3.导入模块的全部信息的第二种方式:
from 模块名 import *
- 4.需要给导入的函数/类/变量重命名时:
from 模块名 import 变量名 as 自定义的名字
也可以给导入的模块名自定义名字
import 模块名 as 自定义的名字
定位模块
- python 搜索被导入模块的顺序为:
- 当前目录 –》shell变量下的PYTHONPATH下的每个目录–》查看默认目录 (unix下,一般为:/usr/local/lib/python/)
- 模块搜索路径存储子啊system模块的sys.path中,可以自己添加
- 1.一般导入方式:
模块制作
- 自定义模块:一个python文件就可以作一个模块,模块的名字就是文件的名字。
- 调用:import 自己的文件名即可
- 测试代码:右键运行可以正常运行,导入的时候,不会运行,用来写模块的时候测试代码
if __name__ == 'main':
要测试的代码
模块中的__all__
- 定义可被其他文件导入的信息
- 格式
__all__ = ['fun1', 'fun2', 'var1']
- 如果一个文件中有__all__变量,则只有__all__变量中的内容可以被其它文件导入,不在__all__变量中的不会被导入
包
多个相关文件的集合,文件夹
导入包中的文件:
import 包名.文件名
如果想一次性导入包里的多个文件,或者设置可以被导入的文件:
- 需要在包下创建文件
__init__.py
__init__.py
文件是用来设置可以被其他文件导入的文件的- 在
__init__.py
文件里写入__all__=['文件名1(不需要加.py后缀)', '文件名2']
则只有文件名为:文件名1和文件名2的两个文件可以被其他文件导入
总结:
- 将有联系的模块放在一起,并创建一个
__init__.py
文件,这个文件夹就叫做一个包 - __init__.py 文件的作用是控制包的导入行为的,如果为空,包中的模块导入不了
- __all__ 变量,是控制在使用
from 模块 import *
语句时,可被导入的内容的 - 可以在__init__.py文件中编写内容,当导入时,就会被执行
- 需要在包下创建文件