1.装饰器详解(重点)
1_1 装饰器
程序运行的时候的记录 -- 日志
在实际工作中,python这样的东西,是放在服务器上运行的
日志其实就是记录下来当前程序的运行,协助我们定位问题
确定问题的方式(通过日志、报错信息去溯源)
import logging # 日志模块
日志模块,会有日志的级别定义
常见的日志级别:
warning:警告
error:报错
debug:调试
info:正常
# 级别是自己设置:我们可以通过自定义级别去确定什么东西该被记录,什么东西不被记录
# 设置的级别,会打印自己以及比自己小的级别信息!!!
# DEBUG > INFO > WARNING > ERROR
logging.basicConfig(level=logging.DEBUG)
日志打印
# logging.info("自定义的info级别的输出内容")
# logging.debug("自定义的info级别的输出内容")
# logging.warning("自定义的info级别的输出内容")
# logging.error("自定义的info级别的输出内容")
日志输出和print打印有一些区别:
# 1.颜色不一样
# 2.语法不一样
# 3.日志打印的时候,会带有用户信息
注意事项:控制台里面的打印,有可能是日志在前,也有可能是print在前(日志和print打印的输出级别没有先后顺序 -- 并行)
装饰器的作用:可以在原有的函数之前、之后进行代码的补充(强化)
语法规则:
def 外层函数(设置一个参数,用来接收调用函数的本体):
def 内置函数():
你要添加的前/后的代码补充
return 内置函数的名称
装饰器的传参
def login_zsq(fun_name):
def login_nzhs(username, password):
print(f"username:{username}")
print(f"password:{password}")
# if username == "admin" and password == "123456":
# print("账号验证成功,允许登录")
fun_name(username, password) # 此时在调用fun4函数,但是fun4函数定义了两个参数,并未传值
return login_nzhs
@login_zsq
def fun4(username, password):
if username == "admin" and password == "123456":
print("账号验证成功,允许登录")
fun4(username="admin", password="123456")
调用装饰器的时候,第一次传参,先给谁?
装饰器里面的内置函数,需要定义参数用来接收
既然内置函数可以接收值,那么原函数fun4怎么接收传进来的值?
在装饰器里面调用原函数执行的时候,把参数同时传递给他
装饰器的规则:
在需要执行函数的头部,加上@符号--如果存在这个@后面的函数名称,就会先去执行这个函数
装饰器的固定写法
2.模块
2_1 模块的概念:
包(package)和模块(module)
包就是python中的文件夹(图标有小圆点、有一个__init__.py文件)
模块就是我们的文件名(不包含.py) 举例:模块的概念
示例:
import time # 模块
# print(time.time()) # 当前时间的时间戳
# time.sleep(3) # 强制等待x秒
# from 模块的路径 import ...
# from 包/模块 import 方法/函数/类/变量/其他的数据信息...
# from time import sleep
# from time import *
# sleep(3)
3.文件的操作
3_1 文件读取:
磁盘:C盘... 500G、1TB、4TB
内存:内存地址,临时存储的空间 16G、24G、32G、64G
python 能够直接读取计算机文件 -- txt、excel、docx、csv、yaml...
语法规则:
open('文件路径', mode='读取方式', encoding='编码格式')
mode: r 读取 w 写入 a 追加写入
直接copy的路径,容易存在转义字符的情况,在引号的前面加一个小写的 r -- 防转义
示例:
file = open(r'/Volumes/attached/hcedu/vipCourse/pythonBasic/python_code/python_0307_234/day07/03 文件操作/load_txt',
mode='r', encoding='utf-8')
# 读取文件 -- read()
# msg = file.read()
# print(f"读取到的内容:{msg}")
# 关闭文件 -- close()
# file.close()
# msg1 = file.read()
# print(f"读取到的内容:{msg1}")
# 问题:那么此时,msg还有没有值?可以的,因为变量的值已经存储在内存中了
# print(f"读取到的内容:{msg}")
# 按行读取 -- readline()
# msg2 = file.readline()
# print(f"读取到的内容:{msg2}")
# 读取所有的内容,按行划分列表元素 -- readlines()
# msg3 = file.readlines()
# print(f"读取到的内容:{msg3}")
# print(len(msg3))
3_2 文件写入:
# w:覆盖写入
# a: 追加写入
file = open("/Volumes/attached/hcedu/vipCourse/pythonBasic/python_code/python_0307_234/day07/03 文件操作/load_txt1",
mode="a", encoding="utf-8")
# w:覆盖写入
# a: 追加写入
# 直接写入 -- write()
file.write("这个是我想写入的内容\n")
file.write("这个是我想写入的内容\n")
file.write("这个是我想写入的内容")
file.write("这个是我想写入的内容")
file.close() # 养成好习惯
3.面向对象
3.1类的定义与实例化对象:
类的里面,称之为方法,类的外面,称之为函数
类名的写法:驼峰式,首字母大写,每个单词紧贴着
定义一个类
class Teacher():
name = "qsdd"
age = 18
sex = "man"
job = "stu"
def eat(self):
print("wowowo")
def teach(self):
print("耶耶")
定义一个对象
qiye = Teacher() # 实例化对象 -- 通过类实例化生成了一个对象 -- qiye
xiaoming = Teacher() # 生成了另外一个对象 -- xiaoming
获取对象中的属性
print(f"""
----->{qiye.name}的自我介绍<-----
name: {qiye.name}
age: {qiye.age}
sex: {qiye.sex}
job: {qiye.job}
""")
调用对象中的方法
qiye.eat()
qiye.teach()
print("-" * 10)
xiaoming.eat()
xiaoming.teach()
修改对象中的属性
xiaoming.name = "dd"
xiaoming.age = 88
xiaoming.sex = "woman"
xiaoming.job = "Majordomo"
print(f"""
----->{xiaoming.name}的自我介绍<-----
name: {xiaoming.name}
age: {xiaoming.age}
sex: {xiaoming.sex}
job: {xiaoming.job}
""")
3.2面向对象的应用
特征:封装、继承、多态
王者荣耀、英雄联盟:Hero -- 每一个英雄是不是都是一个对象?是
示例
"""
英雄名字
英雄的属性
英雄的技能一
英雄的技能二
英雄的技能三
英雄的终极技能
创造4个英雄:对象名字、属性、技能一、技能二、技能三、终极技能
后羿 射手 1.普攻 2.多重箭矢 3.落日余晖 4.灼日之矢
劫、刺客、诸刃、分身、鬼斩、瞬狱影杀阵
王昭君 法师 1.减速 2冰冻 3.冰暴
孙尚香 翻滚突袭 红莲爆弹 究极弩炮 活力迸发
"""
class Hero:
# 构造方法 -- 用来接收实例化对象的时候,传进来的值
# 每次实例化的时候,必定最先执行这个构造方法
def __init__(self, hero_name, hero_attributes, hero_skill_one, hero_skill_two, hero_skill_three,
hero_skill_ultimate):
# 把实例化对象传进来的值,赋值给当前对象的属性
# self:表示当前对象
self.hero_name1 = hero_name # 不一定需要同名的
self.hero_attributes = hero_attributes
self.hero_skill_one = hero_skill_one
self.hero_skill_two = hero_skill_two
self.hero_skill_three = hero_skill_three
self.hero_skill_ultimate = hero_skill_ultimate
def skill_one(self):
# 在类的里面,不同的方法中,调用同一个属性,需要带有self.开头
print(f"{self.hero_name1} -- 释放了技能一:{self.hero_skill_one}")
# print(f"{hero_name1}") # 错误的示范
def skill_two(self):
print(f"{self.hero_name1} -- 释放了技能二:{self.hero_skill_two}")
def skill_three(self):
print(f"{self.hero_name1} -- 释放了技能三:{self.hero_skill_three}")
def skill_ultimate(self):
print(f"{self.hero_name1} -- 释放了终极技能:{self.hero_skill_ultimate}")
# 实例化对象
Houyi = Hero("后羿", "射手", "普攻", "多重箭矢", "落日余晖", "灼日之矢")
Jie = Hero("劫", "刺客", "诸刃", "分身", "鬼斩", "瞬狱影杀阵")
WangZhaoJun = Hero("王昭君", "法师", "减速", "冰冻", "冰暴", "凤求凰")
SunShangXiang = Hero("孙尚香", "射手", "翻滚突袭", "红莲爆弹", "究极弩炮", "活力迸发")
# 获取对象的属性
# print(f"Houyi对象中的名字:{Houyi.hero_name1}")
# print(f"Jie对象中的名字:{Jie.hero_name1}")
# print(f"WangZhaoJun对象中的名字:{WangZhaoJun.hero_name1}")
# print(f"SunShangXiang对象中的名字:{SunShangXiang.hero_name1}")
#
# print("-" * 100)
# 调用对象中的方法
# Houyi.skill_one()
# Jie.skill_one()
# WangZhaoJun.skill_one()
# SunShangXiang.skill_one()
# 练习:
print("-" * 100)
print("英雄登场")
print(f"""
第一个英雄:{Houyi.hero_name1}
英雄的属性:{Houyi.hero_attributes}
英雄的技能一:{Houyi.hero_skill_one}
英雄的技能二:{Houyi.hero_skill_two}
英雄的技能三:{Houyi.hero_skill_three}
英雄的终极技能:{Houyi.hero_skill_ultimate}
""")
print("-" * 100)
print(f"""
第二个英雄:{Jie.hero_name1}
英雄的属性:{Jie.hero_attributes}
英雄的技能一:{Jie.hero_skill_one}
英雄的技能二:{Jie.hero_skill_two}
英雄的技能三:{Jie.hero_skill_three}
英雄的终极技能:{Jie.hero_skill_ultimate}
""")
print("-" * 100)
print(f"""
第三个英雄:{WangZhaoJun.hero_name1}
英雄的属性:{WangZhaoJun.hero_attributes}
英雄的技能一:{WangZhaoJun.hero_skill_one}
英雄的技能二:{WangZhaoJun.hero_skill_two}
英雄的技能三:{WangZhaoJun.hero_skill_three}
英雄的终极技能:{WangZhaoJun.hero_skill_ultimate}
""")
print("-" * 100)
print(f"""
第四个英雄:{SunShangXiang.hero_name1}
英雄的属性:{SunShangXiang.hero_attributes}
英雄的技能一:{SunShangXiang.hero_skill_one}
英雄的技能二:{SunShangXiang.hero_skill_two}
英雄的技能三:{SunShangXiang.hero_skill_three}
英雄的终极技能:{SunShangXiang.hero_skill_ultimate}
""")
print("-" * 100)
print("第一回合:")
Houyi.skill_one()
Jie.skill_two()
WangZhaoJun.skill_three()
SunShangXiang.skill_one()
print("-" * 100)
print("第二回合:")
SunShangXiang.skill_three()
Jie.skill_three()
Houyi.skill_three()
WangZhaoJun.skill_ultimate()
print("-" * 100)
print("第三回合:")
Jie.skill_ultimate()
WangZhaoJun.skill_ultimate()
SunShangXiang.skill_ultimate()
Houyi.skill_ultimate()
4.类中的属性
4.1类属性的定义与调用
实例属性:实例对象的属性
定义在构造方法中的属性
公有实例属性:常规属性
私有实例属性:双下划线开头,只能在自己类中调用
例子如下
class Person:
def __init__(self, name, age, sex, job):
# 公有属性
self.name = name
self.age = age
# 私有属性
self.__sex = sex
self.__job = job
def eat(self):
print(f"{self.name}是一个吃货!")
def get_job(self):
return self.__job
def set_job(self, set_job):
self.__job = set_job
qiye = Person("qsdd", 18, "man", "teacher")
封装 -- 提高数据的安全性,减少误操作
获取私有属性:
# 第一方式获取return
# print(qiye.get_job())
# 第二方式获取return
# job = qiye.get_job()
# print(job)
修改私有属性:
# qiye.set_job("测试")
# print(qiye.get_job())
内置属性:
"""
类名.__dict__ 属性
类名.__doc__ :类的文档字符串
类名.__name__ :类名
类名.__module__ :类定义所在的模块(类的全名是"__main__.className")
类名.__bases__ :类的所有父类构成元素(包含类一个由所有父类组成的元组)
"""
# print(Person.__dict__)
# print(Person.__doc__)
# print(Person.__name__)
# print(Person.__module__)
# print(Person.__bases__)
类的公有和私有方法
类的方法:
私有方法就是两个下划线开头,只能在类中使用的方法
class Person:
# 公有方法
def eat(self):
print("一个吃货!")
# 私有方法
def __work(self):
print("工作:授课")
def invoke_work(self):
# 调用私有方法
self.__work() # 这个可不可以调用私有方法?
print("invoke_work方法的调用")
qiye = Person()
# 调用公有方法
qiye.eat()
# 调用私有方法
# qiye.__work() # 'Person' object has no attribute '__work'
qiye.invoke_work()
5.继承
5_1 单继承
示例如下
class 类名(父类):
子类独有的东西
def 子类任何方法
子类可以享有父类的所有属性和方法
可以省略很多重复性的代码,可以直接使用父类提前写好的方法/属性
class Animal:
def __init__(self):
self.__num = 10
self.lst1 = [1, 2, 3]
def eat(self):
print("动物喜欢吃东西")
def get_num(self):
return self.__num
# 继承父类
class Cat(Animal):
num1 = 100
def shout(self):
print("猫叫:喵喵")
Tom = Cat()
# 调用自己类中的方法/属性
Tom.shout()
print(Tom.num1)
# 调用继承的父类中的方法/属性
Tom.eat()
print(Tom.lst1)
print(Tom.get_num())
5.2继承的传递性:
# 爷爷辈
class Animal:
def __init__(self):
self.__num = 10
self.lst1 = [1, 2, 3]
def eat(self):
print("动物喜欢吃东西")
def get_num(self):
return self.__num
# 父辈
class Cat(Animal):
num1 = 100
def shout(self):
print("猫叫:喵喵")
def eat(self):
print("猫喜欢吃猫粮")
# 子辈
class TomCat(Cat):
lst2 = [1, 2]
def speak(self):
print("hello 我是Tom")
def eat(self):
print("我是Tom, 我喜欢吃肉")
tomcat = TomCat()
# 调用自己类中的属性和方法
# tomcat.speak()
# print(tomcat.lst2)
# 调用父类的属性和方法
# tomcat.shout()
# 调用爷爷辈的属性和方法
# tomcat.eat()
# 当爷爷辈和父辈,同时具备一个同名的方法,执行哪个?
# tomcat.eat()
# 当自己也具备一个同名的方法,执行哪个? -- 执行自己的,也叫做方法的重定义/重写
tomcat.eat()
多继承
语法规则
class 类名(父类1,父类2):
规则和单继承没什么区别
例子如下
class Monkey:
def eat(self):
print("猴子喜欢吃香蕉")
class God:
def fly(self):
print("神仙可以飞")
def eat(self):
print("神仙喜欢吃蟠桃")
# 创建一个类,同时继承多个类
class SunWuKong(God, Monkey):
def buddhist_pilgrimage(self):
print("孙悟空需要去取经")
# 调用自己类的属性和方法
swk = SunWuKong()
swk.buddhist_pilgrimage()
# 调用父类的属性和方法
swk.eat()
swk.fly()
# 问题:如果两个父类,同时有一个同名的方法,调用的时候,执行哪个? -- 就近原则,谁在前面,听谁的
swk.eat()
6.多态
抽象概念:定义好一个制式,按照这个制式向接口去提供对应的不同的对象,根据你提供的不同对象来执行不同的操作
示例:
支付方式:银行卡、微信、支付宝、刷脸...
# 定义一个初始化支付
class PayMent:
def pay(self):
print("请支付!")
# 定义多种不同的支付方式
class WeChat(PayMent):
def pay(self):
print("使用微信支付!")
class AliPay(PayMent):
def pay(self):
print("使用支付宝支付!")
class Card(PayMent):
def pay(self):
print("使用银行卡支付!")
# 定义一个进行支付的类
class StartPay:
def start_pay(self, obj): # 设置一个参数,接收对象
# 当我接收到对象后,开始调用这个对象的方法
obj.pay()
# 实例化对象
sp = StartPay()
wc = WeChat()
alp = AliPay()
cd = Card()
sp.start_pay(obj=wc)
sp.start_pay(obj=alp)
sp.start_pay(obj=cd)