语法基础
- 注释
- 单行注释 #
- 多行注释 “"" xxx “”"
- 变量类型
type(V_name) 查看变量类型
不同的变量类型,占用的内存大小不同- Numbers
- 整形 int
- 长整型 long
- 浮点型 float
- 复数 complex
- 布尔型 bool
- 字符串 str
- 列表 List
- 元组 Tuple
- 字典 Dictionary
- Numbers
- 标识符
由字母,下划线和数字组成,且数字不能开头
区分大小写 - 关键词
特殊功能的标识符
‘False’, ‘None’, ‘True’, ‘__
peg_parser__’, ‘and’, ‘as’, ‘assert’, ‘async’, ‘await’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’, ‘except’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’, ‘lambda’, ‘nonlocal’, ‘not’, ‘or’, ‘pass’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’, ‘yield’
- 输出
- 格式化输出
格式化常用符号- %s 格式化字符串
- %d 格式化整数
- %-2d 显示两位并左对齐,若只有一位则用空格占位,默认右对齐
- %f 格式化浮点数字,可指定小数点后的精度
myAge = 20 print("我的年龄是%d岁" % myAge)
- 转义输出
常用转义字符- \n 换行符
- \t 横向制表符(TAB)
- \0 表示一个空字符
- \v 纵向制表符
- \r 回车符
- \f 换页符
- 格式化输出
- 输入
input得到的结果是String
myName = input("please enter your Name:")
myAge = input("please enter your Age:")
print("Name:%s Age:%s" % (myName,myAge))
-
运算符
- 算术运算符
+ 加;- 减;* 乘;/ 除;// 整除;% 取余;** 指数 - 赋值运算符 =
- 复合赋值运算符
算术运算符复合赋值运算符 - 关系运算符
==;!=;>;<;>=;<= - 逻辑运算符
and;or;not
- 算术运算符
-
常用数据类型转换
- int(x) 将x转换为一个整数
- float(x) 将x转换为一个浮点数
- str(x) 将x转换为一个字符串
- eval(str) 用来计算在字符串中的有效python表达式,并返回一个对象
判断语句和循环语句
- if-elif-else
if 判断条件1:
执行语句1
elif 判断条件2:
执行语句2
else:
执行语句3
- if嵌套(采用缩进区分层次)
money = eval(input("请输入您公交卡的余额:"))
flag = not True
if money >= 2:
print("可以上公交车")
if flag:
print("可以坐下")
else:
print("站一会")
else:
print("请充值后再上车")
- while循环
while 判断条件:
执行语句
循环标识+1
- while循环嵌套
#九九乘法表
x = 1
while x <= 9:
# 定义一个变量 记录列数
y = 1
while y <= x:
print("%d * %d = %-2d" % (y, x, x * y), end=" ")
y += 1
# 换行
print()
x += 1
- for循环
范围函数range()
range(m,n) -> [m,n)
range(n) -> [0,n)
for 临时变量 in 可迭代对象(列表/字符串/...):
执行语句
- break&continue
break:结束所有循环
continue:提前结束本次循环,进入下一次循环 - for-else&while-else
for i in range(5):
print(i)
if i == 2:
#break
else:
print("else")
# while循环
i = 0
while i < 5:
print(i)
if i == 2:
break
i += 1
else:
print("else")
"""
无论for-else 还是 while-else 如果在for循环中 或者 while循环中 没有执行break 待for循环或者while结束后 会执行else中的代码
当for循环或者while循环中的break执行 else中的代码将不会执行
"""
- 字符串
字符串 -> 有序的字符序列- 索引
从左到右0,1,2…
从右到左-1,-2,-3… - 切片 [start,end,step] 范围[start,end)
- 常见操作
- len(str) 获取字符串长度
- mystr = “”“文本内容”"" 保留拷贝的文本格式
- mystr.find(“str”) 获取对应字符串的下标索引,如果未查询到,返回-1;
- mystr.index(“str”) 获取对应字符串的下标索引,如果未查询到,返回异常;
- mystr.count(str,start=0,end=len(myStr)) 返回str在start和end之间在mystr中出现的次数;
- mystr.replace(str1,str2,n) 把myStr中的str1替换成str2;如果n指定,则不超过n次;
- mystr.split(str=" ",2) 以str为分隔符,切片mystr,返回一个列表;如果n指定,则仅分隔n个字符串;
- mystr.capitalize() 把字符串的第一个字符大写;
- mystr.title() 把字符串的每个单词首字母大写;
- mystr.startswith(obj)检查字符串是否是以 obj开头, 是则返回 True,否则返回 False;
- mystr.endswith(obj) 检查字符串是否以obj结束,如果是返回True,否则返回 False;
- mystr.lower() 转换字符串中所有大写字符为小写;
- mystr.upper() 转换字符串中的小写字母为大写;
- mystr.ljust(width,fillchar) 返回一个原字符串左对齐,并使用指定fillchar[默认空格]填充至长度 width 的新字符串
- mystr.rjust(width,fillchar) 返回一个原字符串右对齐,并使用指定fillchar[默认空格]填充至长度 width 的新字符串
- mystr.center(width,fillchar) 返回一个原字符串居中,并使用指定fillchar[默认空格]填充至长度 width 的新字符串
- mystr.lstrip() 删除 mystr 左边的空白字符
- mystr.rstrip() 删除 mystr 字符串末尾的空白字符
- mystr.strip() 删除mystr字符串两端的空白字符
- mystr.rfind(str, start=0,end=len(mystr) ) 类似于find(),不过是从右边开始.
- mystr.rindex( str, start=0,end=len(mystr)) 类似于 index(),不过是从右边开始
- mystr.partition(str) 把mystr以str分割成三部分,str前,str和str后
- mystr.rpartition(str) 类似于 partition()函数,不过是从右边开始.
- mystr.splitlines() 按照行分隔,返回一个包含各行作为元素的列表
- mystr.isalpha() 如果 mystr 所有字符都是字母 则返回 True,否则返回 False
- mystr.isdigit() 如果 mystr 只包含数字则返回 True 否则返回 False.
- mystr.isalnum() 如果 mystr 所有字符都是字母或数字则返回 True,否则返回 False
- mystr.isspace() 如果 mystr 中只包含空格,则返回 True,否则返回 False.
- mystr.join(str) mystr中每个元素后面插入str,构造出一个新的字符串
- 索引
列表
- 定义
my_list =[元素1,元素2,…] - 索引
- 从左到右0,1,2…
- 从右到左-1,-2,-3…
- 列表的循环遍历
- for循环
- while循环
namesList = ['xiaoWang','xiaoZhang','xiaoHua']
for name in namesList:
print(name)
length = len(namesList)
i = 0
while i<length:
print(namesList[i])
i+=1
- 常见操作
- 添加元素
- append
添加一个整体 - extend
添加一个可以遍历的对象;将另一个集合中的元素逐一添加到列表中 - insert(index, object)
在指定位置index前插入元素object
- append
>>> a = [1, 2] >>> b = [3, 4] >>> a.append(b) >>> a [1, 2, [3, 4]] >>> a.extend(b) >>> a [1, 2, [3, 4], 3, 4] >>> a.insert(1, 3) >>> a [1, 3, 2, [3, 4], 3, 4]
- 修改元素
A = ['xiaoWang','xiaoZhang','xiaoHua'] #修改元素 A[1] = 'xiaoLu'
- 查找元素
- in, not in
nameList = ['xiaoWang','xiaoZhang','xiaoHua'] findName = input('请输入要查找的姓名:') #查找是否存在 if findName in nameList: print('找到了') else: print('没有找到')
- index
返回查找元素的下标索引 - count
>>> a = ['a', 'b', 'c', 'a', 'b'] >>> a.index('a', 1, 3) # 注意是左闭右开区间 Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: 'a' is not in list >>> a.index('a', 1, 4) 3 >>> a.count('b') 2 >>> a.count('d') 0
- 删除元素
- del
根据下标进行删除
可以用来删除对象,提前释放内存 - pop
删除最后一个元素,且会有一个返回值 - remove
根据元素的值进行删除
movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情'] del movieName[2] #根据下标进行删除 movieName.pop() #删除最后一个元素 movieName.remove('指环王') #根据元素的值进行删除
- del
- 排序
sort,reverse
>>> a = [1, 4, 2, 3] >>> a [1, 4, 2, 3] >>> a.reverse() #降序 >>> a [3, 2, 4, 1] >>> a.sort() >>> a [1, 2, 3, 4] >>> a.sort(reverse=True) >>> a [4, 3, 2, 1]
- 添加元素
- 列表的嵌套
schoolNames = [['北京大学','清华大学'],['南开大学','天津大学','天津师范大学'],['山东大学',["新东方", "蓝翔"],'中国海洋大学']]
name = schoolNames[1][1]
print(name)
元组
列表是可变的,元组是不可变的
- 定义
my_tuple = (元素1,元素2,…) - 注意
如果元组只有一个元素,不为元组类型;可以加个逗号
(1)–> int;(1,)–>tuple - 常见操作
- 访问元组
通过下标索引 - 查找元素
- index
- count
- 访问元组
字典
键值对{key:value,…};字典是无序的,可变的
-
定义
my_dict = {key1:value1,key2:value2,…}
key值类型必须是不可变的(如列表、字典等都不可),且不能重复(才能完成1对1),一般都使用字符串 -
常见操作
-
修改元素/添加元素
格式:字典名[key] = value
如果key不存在,则添加一组键值对;如果key存在,则会覆盖此key原来的值 -
删除元素
- del
删除指定元素,也可以删除整个字典 - clear
清空整个字典
>>> info = { 'name':'班长', 'sex':'f', 'address':'地球亚洲中国北京'} >>> del info['name'] >>> print('删除后,%s' % info['name']) Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'name' del info #删除整个字典 info.clear() #清空整个字典 结果为{}
- del
-
len() 返回键值对的个数
-
keys 返回一个包含字典所有key的列表
-
values 返回一个包含字典所有value的列表
-
items 返回一个包含所有(键,值)元祖的列表
-
-
遍历
my_dict = {
"name": "小红", "age": 22, "no": "009"}
# 遍历-key
for key in my_dict.keys():
print(key)
# 遍历value
for value in my_dict.values():
print(value)
# 遍历items
for item in my_dict.items():
print(item[0])
# 通过设置两个临时变量
for key, value in my_dict.items():
print("key:", key)
print("value:", value)
# enumerate(列表名) 函数
# enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标
my_list = list("abcd")
# 不仅要获取列表中的元素 而且需要知道这个元素下标索引
for i, value in enumerate(my_list):
print(i,value)
拆包
变量名和值一一对应
可以把函数返回值直接拆包
name,age,no,address = ("zhangsan",20,1,"didian")
name,age,no,address = ["zhangsan",20,1,"didian"]
name,age,no,address = {
"name":"zhangsan","age":20,"no":1,"address":"didian"} #取到的是key值
#批量定义变量
num1, num2, num3, num4 = 10, 20, 30, 40
函数
- 定义
def 函数名(形参1,形参2,...):
函数体
# pass占位,防止错误
- 调用
函数名(实参1,实参2,...)
- 缺省参数
给形参设置一个默认值;调用函数时,可根据实际需要决定是否传递参数必须先定义后调用,有先后顺序
注意:在定义函数时若某个形参使用了缺省参数,那么其后面的形参都需要用缺省参数 - 四种函数类型
- 无参数、无返回值
- 无参数、有返回值
- 有参数、无返回值
- 有参数、有返回值
- 函数可嵌套调用
- 调用函数方式
- 位置参数
使用位置参数调用函数,需要注意实参的位置–>实参的位置需要和形参的位置一一对应 - 关键字参数
调用函数的时候使用的是函数的形参名,位置不需要完全对应
- 位置参数
- 函数返回值return
只要函数中执行了return,提前结束函数的执行,且其后的代码将不再执行;可以通过return使执行的函数提前结束以优化性能
可以直接返回不同类型的数据;如return a,b --> tuple return […] --> list ; return{ “key”:value,“key2”:value,…} --> dict ; - 函数的文档说明
- 如果一个自定义函数没有文档说明 ,默认用help会打印函数上面的注释
- 可以在def下方用""" “”"自动生成文档说明
- 变量
- 局部变量
定义在函数内部,作用域仅在函数内部 - 全局变量
定义在函数外部,作用域为整个模块;
标识全局变量 --> global 变量名 - 优先级
局部变量>全局变量;python会现在函数内部找变量,若无,再在外部找
- 局部变量
- 匿名函数lambda
# 对函数的简写
f = lambda a, b : a + b
print(f(10, 20))
# 等价于
# def add2num(a, b):
# return a + b
# 函数作为参数传递
# f = lambda x,y:x+y
def fun(a, b, opt):
result = opt(a, b)
print("result = %d" % result)
fun(1, 2, lambda x,y:x+y)
# 自定义排序(最外层肯定是列表)
# 格式: 列表名.sort(key=lambda 列表的元素(临时变量): 临时变量[key])
stus = [{
"name": "zhangsan", "age": 18}, {
"name": "lisi", "age": 19}, {
"name": "wangwu", "age": 17}]
# 按照年龄排序
stus.sort(key=lambda my_dict:my_dict["age"])
# 按照名字排序
stus.sort(key=lambda my_dict:my_dict["name"])
# 列表中的列表嵌套
my_list = [[10, 8, 9], [7, 10, 19], [9, 10, 29]]
# 按照列表元素(小列表)最后一个元素排序
my_list.sort(key=lambda new_list:new_list[2], reverse=True)
- 列表推导式
快速创建有规律的列表
# 使用列表推导式 快速创建一个列表
my_list = [ i for i in range(1, 31)]
# 等价于
# my_list = []
# for i in range(1, 101):
# my_list.append(i)
# 得到一个有30个哈哈的列表
my_list = ["哈哈" for i in range(30)]
# 定义一个列表 保存数据[1, 50]之间的偶数
# 列表推导式
my_list = [ i for i in range(1, 51) if i % 2 == 0]
# 等价于
# my_list = []
# for i in range(1, 51):
# # 判断是否是偶数
# if i % 2 == 0:
# my_list.append(i)
#
# print(my_list)
文件操作
- 文件打开与关闭
# 打开一个文件 以只读方式 返回一个文件对象
# 如果使用r模式打开文件,如果文件存在,直接打开;如果文件不存在 会报错
f = open("hm.txt", "r")
# 关闭文件(打开一个文件就需要消耗内存)
f.close()
# 打开一个文件 以只写方式 返回一个文件对象;如果以w方式打开文件 会把原来文件的数据清空 然后在写入
# 如果使用w模式打开文件 如果文件存在 直接打开;如果文件不存在 会创建一个文件 然后打开
open("hm.txt", "w")
f.close()
# a 追加数据
# f = open(file_name, "a")
# f.write("nihao")
# f.close()
- 文件读写
file_name = "hm.txt"
# <1>写数据(write)
# f = open(file_name, "w")
# f.write("hello world")
# f.close()
# <2>读数据(read) 如果使用字符串方便
# f = open(file_name, "r")
# ret = f.read()
# print(ret)
# f.close
# <3>读数据(readlines) 如果使用列表方便
# f = open(file_name, "r")
# 把每行的数据保存到列表中
# ret = f.readlines()
# print(ret)
# f.close()
# 中文读写
# f = open("hmhm.txt", "w", encoding="utf-8")
# # 写入数据
# # 默认情况下如果在windows电脑中(中国) 保存中文编码格式为gbk (mac电脑或者是linux 没有问题)
# # 如果其他字符 例如abcd 编码格式为utf-8
# f.write("你好世界")
# # 关闭文件
# f.close()
- 其他操作
导入os模块
import os
# 文件/文件夹重命名
os.rename(old_fileName,new_fileName)
# 删除文件
os.remove(fileName)
# 创建文件夹
os.mkdir(dirName)
# 获取当前目录(绝对路径)
result = os.getwd()
# 改变默认目录
os.chdir("../")
# 获取目录列表
my_list = os.listdir()
# 删除文件夹
os.rmdir(dirName)
- 其他类型文件操作
- txt文件
# 读取 # 通过此方式打开文件 不需要关闭 # as 是给文件起了名字 with open("hm.txt", "r", encoding="utf-8") as f: result = f.read() # 写入 f = open("hm.txt", "w", encoding="utf-8") f.write("hello python!!!") f.close()
- excel文件
# 读取 import xlrd data = xlrd.open_workbook("student.xlsx") # 获取列表 table = data.sheet_by_index(0) # 获取所有的行数 nrows = table.nrows # 获取所有的列数 ncols = table.ncols # 获取第一行的数据 first_row_name_list = table.row_values(0) print(first_row_name_list) # 定义一个列表保存所有行的数据 info_list = [] # 遍历所有行 for rownum in range(1, nrows): row = table.row_values(rownum) if row: info_list.append(row) print(info_list) # 写入 import xlsxwriter # 打开student.xlsx文件 workbook = xlsxwriter.Workbook("student.xlsx") # 创建一张工作表 worksheet = workbook.add_worksheet() # 设置第一行信息 worksheet.write(0, 0, "学号") worksheet.write(0, 1, "姓名") worksheet.write(0, 2, "年龄") # 学生信息列表 student_list = [{ "name": "小明", "age": 20, "no": "20170901001"}, { "name": "小红", "age": 21, "no": "20170901002"}, { "name": "小刚", "age": 20, "no": "20170901003"}, { "name": "小海", "age": 23, "no": "20170901004"}, { "name": "小阳", "age": 25, "no": "20170901005"}] # 遍历列表 for i, info in enumerate(student_list): # 写入数据 # write(第x行, 第x列, 写入的数据) worksheet.write(i + 1, 0, info["no"]) worksheet.write(i + 1, 1, info["name"]) worksheet.write(i + 1, 2, info["age"]) # 关闭文件 workbook.close()
- json文件
# 读取 import json # 将json对象转成字典 -> 进行解码 with open("hm.json", "r", encoding="utf-8") as f: # 获取文件中数据 -> 字典 new_dict = json.load(f) # 查看类型 print(type(new_dict)) # 获取名字 print(new_dict["name"]) # 获取年龄 print(new_dict["age"]) # 获取学号 print(new_dict["no"]) # 写入 import json # 定义一个字典 my_dict = { "name": "老王", "age": 30, "no": "007"} # 将字典转成json -> 进行编码 json_str = json.dumps(my_dict) # 打印json字符串 print(type(json_str)) # 把json数据写入到文件中 with open("hm.json", "w", encoding="utf-8") as f: f.write(json_str)
- xml文件
// xml示例文件 <list> <music title="再见理想"> <format>盒带</format> <year>1986</year> <month>3</month> <stars>10</stars> <description>Beyond出品</description></music><music title="光辉岁月"> <format>盒带</format> <year>1987</year> <month>1</month> <stars>9</stars> <description>Beyond出品</description></music> <music title="长城"> <format>盒带</format> <year>1992</year> <month>8</month> <stars>10</stars> <description>Beyond出品</description></music><music title="海阔天空"> <format>盒带</format> <year>1993</year> <month>6</month> <stars>10</stars> <description>Beyond出品</description></music></list>
# 读取 import xml.dom.minidom # 定义一个变量保存文件名 file_name = "xml.xml" #打开xml文档 domTree = xml.dom.minidom.parse(file_name) # 返回文档的根节点 root = domTree.documentElement # 返回带有指定标签名的对象的集合(在集合中获取所有电影) musics = root.getElementsByTagName("music") # 打印每部电影的详细信息 for music in musics: print("------音乐------") # 如果元素的属性为title if music.hasAttribute("title"): print("歌名: %s" % music.getAttribute("title")) # 格式 type = music.getElementsByTagName("format")[0] print("-格式: %s" % type.childNodes[0].data) year = music.getElementsByTagName("year")[0] print("-年份: %s" % year.childNodes[0].data) month = music.getElementsByTagName("month")[0] print("-月份: %s" % month.childNodes[0].data) start = music.getElementsByTagName("stars")[0] print("-星数: %s" % start.childNodes[0].data) desc = music.getElementsByTagName("description")[0] print("-描述:%s" % desc.childNodes[0].data)
面向对象基础
-
区分
- 面向过程
根据业务逻辑从上到下写代码 - 面向对象(封装成类,可复用)
将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程
面向对象三大特性:封装、继承、多态
- 面向过程
-
类和对象
- 定义
- 类(抽象)
类名、属性、方法 - 实例对象
- 类(抽象)
- 自定义类
class 类名:
方法列表
# class Hero: # 经典类(旧式类) # class Hero(): class Hero(object): # 新式类 def info(self): print("英雄各有见,何必问出处。") # object 是Python 里所有类的最顶级父类; # 类名 的命名规则按照"大驼峰命名法"; # info 是一个实例方法,第一个参数一般是self,表示实例对象本身,当然了可以将self换为其它的名字,其作用是一个变量 这个变量指向了实例对象
- 创建对象
对象名1 = 类名()
对象名2 = 类名()
对象名3 = 类名()
class Hero(object): # 新式类 # 1、定义实例方法 def info(self): """当对象调用实例方法时,Python会自动将对象本身的引用做为参数, 传递到实例方法的第一个参数self里""" print(self) print("self各不同,对象是出处。") # Hero这个类 2、实例化了一个对象 taidamier(泰达米尔) taidamier = Hero() # 3、对象调用实例方法info(),执行info()里的代码 # . 表示选择属性或者方法 taidamier.info()
- 添加和获取对象的属性
class Hero(object): def move(self): """实例方法""" print("正在前往事发地点...") def attack(self): print("发出了一招强力的普通攻击...") # 实例化了一个英雄对象 泰达米尔 taidamier = Hero() # 给对象添加属性,以及对应的属性值 taidamier.name = "泰达米尔" # 姓名 taidamier.hp = 2600 # 生命值 taidamier.atk = 450 # 攻击力 taidamier.armor = 200 # 护甲值 # 通对.成员选择运算符,获取对象的属性值 print("英雄 %s 的生命值 :%d" % (taidamier.name, taidamier.hp)) print("英雄 %s 的攻击力 :%d" % (taidamier.name, taidamier.atk)) print("英雄 %s 的护甲值 :%d" % (taidamier.name, taidamier.armor)) # 通过.成员选择运算符,获取对象的实例方法 taidamier.move() taidamier.attack()
- 在方法内通过self获取对象属性
class Hero(object): def move(self): print("正在前往事发地点...") def attack(self): print("发出了一招强力的普通攻击...") def info(self): """在类的实例方法中,通过self获取该对象的属性""" print("英雄 %s 的生命值 :%d" % (self.name, self.hp)) print("英雄 %s 的攻击力 :%d" % (self.name, self.atk)) print("英雄 %s 的护甲值 :%d" % (self.name, self.armor)) # 实例化了一个英雄对象 泰达米尔 taidamier = Hero() # 给对象添加属性,以及对应的属性值 taidamier.name = "泰达米尔" # 姓名 taidamier.hp = 2600 # 生命值 taidamier.atk = 450 # 攻击力 taidamier.armor = 200 # 护甲值 # 通过.成员选择运算符,获取对象的实例方法 taidamier.info() # 只需要调用实例方法info(),即可获取英雄的属性 taidamier.move() taidamier.attack()
- 定义
-
魔法方法
__开头,__结尾的方法,是python内置的方法,在特殊情况下被python执行(python可以监听到你使用自定义类创建一个对象)
在自定义类中重写魔法方法- __init__()方法
监听python使用其类创建对象完成,给这个对象设置属性
在创建一个对象时默认被调用,不需要手动调用
class Hero(object): """定义了一个英雄类""" def __init__(self, name, skill, hp, atk, armor): """ __init__() 方法,用来做变量初始化 或 赋值 操作""" self.name = name self.skill = skill self.hp = hp self.atk = atk self.armor = armor def move(self): """实例方法""" print("%s 正在前往事发地点..." % self.name) def attack(self): print("发出了一招强力的%s..." % self.skill) def info(self): print("英雄 %s 的生命值 :%d" % (self.name, self.hp)) print("英雄 %s 的攻击力 :%d" % (self.name, self.atk)) print("英雄 %s 的护甲值 :%d" % (self.name, self.armor)) # 实例化英雄对象时,参数会传递到对象的__init__()方法里 taidamier = Hero("泰达米尔", "旋风斩", 2600, 450, 200) gailun = Hero("盖伦", "大宝剑", 4200, 260, 400) # 不同对象的属性值单独保存 print(id(taidamier.name)) print(id(gailun.name)) # 同一个类的不同对象,实例方法共享 print(id(taidamier.move())) print(id(gailun.move()))
- __new__()方法
监听python使用其类创建对象,并返回对象 --> init
class A(object): def __init__(self): print("这是 init 方法") def __new__(cls): print("这是 new 方法") return object.__new__(cls) A() # __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供 # __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例 # __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值 # 我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节
- __str__()方法
监听对象属性信息的变化,会返回一个字符串,不能添加参数,一般用于调试代码
如果类中实现了__str__()方法,打印对象名,会输出__str__()方法的返回值
class Hero(object): def __init__(self, name, skill, hp, atk, armor): self.name = name self.skill = skill self.hp = hp self.atk = atk self.armor = armor def move(self): print("%s 正在前往事发地点..." % self.name) def attack(self): """实例方法""" print("发出了一招强力的%s..." % self.skill) def __str__(self): return "英雄 <%s> 数据: 生命值 %d, 攻击力 %d, 护甲值 %d" % (self.name, self.hp, self.atk, self.armor) taidamier = Hero("泰达米尔", "旋风斩", 2600, 450, 200) gailun = Hero("盖伦", "大宝剑", 4200, 260, 400) # 如果没有__str__ 则默认打印对象在内存的地址。 # 当类的实例化对象 拥有 __str__ 方法后,那么打印对象则打印 __str__ 的返回值。 print(taidamier) print(gailun)
- __del__()方法
监听对象销毁后调用的方法
class Hero(object): # 初始化方法,创建完对象后会自动被调用 def __init__(self, name): print('__init__方法被调用') self.name = name # 当对象被删除时,会自动被调用 def __del__(self): print("__del__方法被调用") print("%s 被 GM 干掉了..." % self.name) # 创建对象 taidamier = Hero("泰达米尔") # 删除对象 print("%d 被删除1次" % id(taidamier)) del(taidamier) gailun = Hero("盖伦") gailun1 = gailun gailun2 = gailun print("%d 被删除1次" % id(gailun)) del(gailun) print("%d 被删除1次" % id(gailun1)) del(gailun1) print("%d 被删除1次" % id(gailun2)) del(gailun2)
- 内存回收机制(粗略)
当使用del() 删除变量指向的对象时,则会减少对象的引用计数。如果对象的引用计数不为1,那么会让这个对象的引用计数减1,当对象的引用计数为0的时候,则对象才会被真正删除(内存被回收)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ZR9vzfA-1612875771802)(en-resource://database/1124:1)] @w=300h=400 - 注意
在类内部获取 属性 和 实例方法,通过self获取;
在类外部获取 属性 和 实例方法,通过对象名获取。
- __init__()方法
-
继承
- 单继承
只继承一个父类
# 定义一个Master类 class Master(object): def __init__(self): # 属性 self.kongfu = "古法煎饼果子配方" # 实例方法 def make_cake(self): print("按照 <%s> 制作了一份煎饼果子..." % self.kongfu) # 定义Prentice类,继承Master class Prentice(Master): # 子类可以继承父类所有的属性和方法 pass # laoli = Master() # print(laoli.kongfu) # laoli.make_cake() damao = Prentice() # 创建子类实例对象 print(damao.kongfu) # 子类对象可以直接使用父类的属性 damao.make_cake() # 子类对象可以直接使用父类的方法
- 多继承
如果多个父类中有同名的 属性和方法,则默认使用第一个父类的属性和方法(根据类的魔法属性mro的顺序来查找)
class Master(object): def __init__(self): self.kongfu = "古法煎饼果子配方" def make_cake(self): print("[古法] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu) def dayandai(self): print("师傅的大烟袋..") class School(object): def __init__(self): self.kongfu = "现代煎饼果子配方" def make_cake(self): print("[现代] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu) def xiaoyandai(self): print("学校的小烟袋..") class Prentice(Master, School): # 多继承(Master在前) pass damao = Prentice() print(damao.kongfu) # 执行Master的属性 damao.make_cake() # 执行Master的实例方法 # 子类的魔法属性__mro__决定了属性和方法的查找顺序 print(Prentice.__mro__) damao.dayandai() # 不重名不受影响 damao.xiaoyandai()
- 重写
子类继承父类,做自己特有的事情
子类和父类的方法名和属性名相同,则默认使用子类的 - 子类调用父类同名属性和方法(已重写)
父类类名.父类方法(self) --> self指定调用的对象
class Master(object): def make_cake(self): print("按照 [古法] 制作了一份煎饼果子...") class School(object): def make_cake(self): print(" 按照 [现代] 制作了一份煎饼果子...") # 多继承,继承了多个父类 class Prentice(School, Master): # 实例方法 def make_cake(self): print("按照 [猫氏] 制作了一份煎饼果子...") # 调用父类方法格式:父类类名.父类方法(self) def make_old_cake(self): # 调用父类Master的实例方法 Master.make_cake(self) def make_new_cake(self): # 调用父类School的实例方法 School.make_cake(self) # 实例化对象,自动执行子类的__init__方法 damao = Prentice() damao.make_cake() # 调用子类的方法(默认重写了父类的同名方法) damao.make_old_cake() # 进入实例方法去调用父类Master的方法 damao.make_new_cake() # 进入实例方法去调用父类School的方法 damao.make_cake() # 调用本类的实例方法
- super()方法
super()默认会调用第一个父类的方法(适用于单继承或者只想使用第一个父类方法的多继承)
class Master(object): def make_cake(self): print("按照 [古法] 制作了一份煎饼果子...") class School(Master): def make_cake(self): print("按照 [现代] 制作了一份煎饼果子...") # 执行父类的实例方法 -->可以直接在子类一个方法里面调用父类 super().make_cake() class Prentice(School, Master): def make_cake(self): print("按照 [猫氏] 制作了一份煎饼果子...") def make_all_cake(self): # 方式1. 指定执行父类的方法(代码臃肿) # School.make_cake(self) # Master.make_cake(self) # 方法2. super() 带参数版本,只支持新式类 # super(Prentice, self).make_cake() # self.make_cake() # 方法3. super()的简化版,只支持新式类 # 执行父类的 实例方法 super().make_cake() damao = Prentice() damao.make_cake() damao.make_all_cake()
- 单继承
-
私有属性和私有方法
在属性和方法名前面加了2个下划线’__’,则表明该属性和方法是私有权限,否则为公有权限 -->类似java里的public&private
1. 类的私有属性 和 私有方法,都不能通过对象直接访问,但是可以在本类内部访问;
2. 类的私有属性 和 私有方法,都不会被子类继承,子类也无法访问;
3. 私有属性 和 私有方法 往往用来处理类的内部事情,不通过对象处理,起到安全作用。class Master(object): def __init__(self): self.kongfu = "古法煎饼果子配方" def make_cake(self): print("[古法] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu) class School(object): def __init__(self): self.kongfu = "现代煎饼果子配方" def make_cake(self): print("[现代] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu) class Prentice(School, Master): def __init__(self): self.kongfu = "猫氏煎饼果子配方" # 私有属性,可以在类内部通过self调用,但不能通过对象访问 self.__money = 10000 # 私有方法,可以在类内部通过self调用,但不能通过对象访问 def __print_info(self): print(self.kongfu) print(self.__money) def make_cake(self): self.__init__() print("[猫氏] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu) def make_old_cake(self): Master.__init__(self) Master.make_cake(self) def make_new_cake(self): School.__init__(self) School.make_cake(self) class PrenticePrentice(Prentice): pass damao = Prentice() # 对象不能访问私有权限的属性和方法# print(damao.__money) # damao.__print_info() pp = PrenticePrentice() # 子类不能继承父类私有权限的属性和方法 print(pp.__money) pp.__print_info()
- 修改私有属性的值
间接通过公有方法
class Master(object): def __init__(self): self.kongfu = "古法煎饼果子配方" def make_cake(self): print("[古法] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu) class School(object): def __init__(self): self.kongfu = "现代煎饼果子配方" def make_cake(self): print("[现代] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu) class Prentice(School, Master): def __init__(self): self.kongfu = "猫氏煎饼果子配方" # 私有属性,可以在类内部通过self调用,但不能通过对象访问 self.__money = 10000 # 现代软件开发中,通常会定义get_xxx()方法和set_xxx()方法来获取和修改私有属性值。 # 返回私有属性的值 def get_money(self): return self.__money # 接收参数,修改私有属性的值 def set_money(self, num): self.__money = num def make_cake(self): self.__init__() print("[猫氏] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu) def make_old_cake(self): Master.__init__(self) Master.make_cake(self) def make_new_cake(self): School.__init__(self) School.make_cake(self) class PrenticePrentice(Prentice): pass damao = Prentice() # 对象不能访问私有权限的属性和方法 # print(damao.__money) # damao.__print_info() # 可以通过访问公有方法set_money()来修改私有属性的值 damao.set_money(100) # 可以通过访问公有方法get_money()来获取私有属性的值 print(damao.get_money())
- 修改私有属性的值
-
多态
定义时的类型和运行时的类型不一样;python中弱化类型(重点在于对象参数是否有指定的属性和方法,如果有就认定合适,而不关心对象的类型是否正确 --> “鸭子类型”)
class F1(object):
def show(self):
print('F1.show')
class S1(F1):
def show(self):
print('S1.show')
class S2(F1):
def show(self):
print('S2.show')
def Func(obj):
# python是弱类型,即无论传递过来的是什么,obj变量都能够指向它,这也就没有所谓的多态了(弱化了这个概念)
print(obj.show())
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
- 内存问题
- 对象需要占用内存,且和对象属性地址不同
- 对象的属性也要占用内存,且和对象的地址不同
- 不同的对象,调用对象方法的地址相同(因为方法中有形参self,可以区分是哪个对象调用的)
- python的小整数缓存池(-5~256之间) id相同
- 字符串 元组 字典 列表 也有缓存池(小于2kb)
- 类属性和实例属性
# 类属性就是类对象所拥有的属性
class People(object):
name = 'Tom' # 公有的类属性
__age = 12 # 私有的类属性
p = People()
# 实例属性就是对象属性
class People(object):
address = '山东' # 类属性
def __init__(self):
self.name = 'xiaowang' # 实例属性
self.age = 20 # 实例属性
p = People()
# 若需要在类外修改类属性,必须通过类对象(Peole.name = 'xx')去引用然后进行修改。
# 如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性
- 类中的方法
- 实例方法
- 类方法
class People(object): country = 'china' #类方法,用classmethod来进行修饰 @classmethod def get_country(cls): return cls.country @classmethod def set_country(cls,country): cls.country = country p = People() print(p.get_country()) #可以用过实例对象引用 print(People.get_country()) #可以通过类对象引用 # 对类属性进行修改 p.set_country('japan') print(p.get_country()) print(People.get_country())
- 静态方法
class People(object): country = 'china' #静态方法 @staticmethod def get_country(): #没有默认形参 return People.country p = People() # 通过对象访问静态方法 p.get_contry() # 通过类访问静态方法 print(People.get_country())
- 总结
- 实例方法(对象方法) -> 场景很多 - 定义格式: def 实例方法名(self): - 调用格式: 对象名.实例方法名() - 使用场景: 在方法中需要self - 类方法-> 对私有类属性取值或者赋值 - 定义格式: @classmethod def 类方法名(cls): - 调用格式: 类名.类方法名() 或者 对象名.类方法名() - 使用场景: 在方法中需要cls(类名) - 静态方法 -> 一般不用 - 定义格式: @staticmethod def 静态方法名(): - 调用格式: 类名.类方法名() 或者 对象名.类方法名() - 使用场景: 在方法中不需要self 也不需要cls
- 单例模式(设计模式)–> 节约内存
- 定义
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式
单例模式:在程序中这个类创建出来的对象只有一个,也就是只占用一份内存;也**只会运行一次__init __()方法 **–>保证对象地址唯一,保证其对象的属性只会被赋值一次
- 定义
# 实例化一个单例
class Singleton(object):
__instance = None
__is_first = True
def __new__(cls, age, name):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self, age, name):
if self. __is_first:
self.age = age
self.name = name
Singleton. __is_first = False
a = Singleton(18, "小明")
b = Singleton(28, "小明")
print(id(a))
print(id(b))
print(a.age)
print(b.age)
a.age = 19
print(b.age)
异常
- 捕获异常
- try…except
try: 执行可能发生异常的代码 except (异常类型1,异常类型2,...): #单个异常,多个异常,所有异常(except Exception:...) 如果发生异常执行的代码
- 获取异常信息描述
try: 执行可能发生异常的代码 except (异常类型1,异常类型2,...)as 临时变量: 可以获得临时变量 #print("exceptions",e)
- try…exceprt…else
else后跟未发生异常的代码 - try…except…finally
finally后跟必须要执行的代码
- 异常的传递
- try嵌套中
try嵌套,那么如果里面的try没有捕获到这个异常,那么外面的try会接收到这个异常,然后进行处理,如果外边的try依然没有捕获到,那么再进行传递
import time try: f = open('test.txt') try: while True: content = f.readline() if len(content) == 0: break time.sleep(2) print(content) finally: f.close() print('关闭文件') except: print("没有这个文件")
- 函数嵌套中
def my_func1(): try: print(num) except: print("异常") def my_func2(): my_func1() def my_func3(): my_func2() my_func3()
- try嵌套中
模块
- 模块介绍
变量(全局变量 局部变量 实例属性 类属性)–> 方法(实例方法 类方法 静态方法)–>模块–> 包–>工程(项目)- import
引入格式:import 模块名
使用格式:模块名.全局变量名;模块名.函数名;模块名.类名 - from…import
格式:from 模块名 import 全局变量 函数 类
注意:和本模块名字冲突
from 模块名 *:全部导入,使用时不需要写模块名 - 关键词as–>别名
- 关键词__all__
如果一个模块中使用了__all__,列表中的字符串才可以在其他模块中使用;但其他模块必须是通过from…import * 方式导入的模块 - 包
导入格式:包名.模块名 as 别名
- import
转载:https://blog.csdn.net/weixin_45890734/article/details/113775662