1、面向对象的扩展:魔法方法【重点】
疑问:面相对象是什么?到底应该怎么用?
面向对象:分(类和对象)–>分(特征和属性方法)–>总(项目收尾)
什么是魔法方法:魔法方法是一种特殊的方法,从Object继承而来,在类型中体现为两个下划线开头和结尾的方法,有一地你给的特殊作用,如__str__()方法用于在直接打印输出对象时,展示给用户的字符串信息,默认情况下是内存地址,开发人员可以按照自己的需要进行自定义输出。
__class__ : 魔法属性,用于查看当前对象的类型,类似type()操作
__delattr__ :魔法方法,用于删除当前对象的一个属性
__dict__ :魔法方法,将对象中的数据按照字典的形式输出
__dir__ :魔法方法,和dir() 类似,查看当前类型/对象,都有哪些操作
__doc__ :魔法属性,用于查看当前对象的文档注释
# 代码1:比较两个人的年龄大小
class Person:
"""人"""
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person("大牧", 18)
p2 = Person("小李", 16)
# 比较两个人的年龄
print(p1.age > p2.age)
魔法方法中的算数运算
__ge__(other):对应的比较符号:>|<
__eq__(other):对应的比较符号:==|!=
__lt__(other):对应的比较符号:<
__le__(other):对应的比较符号:< =
魔法方法操作
> : grant than : gt
< : less than : lt
== : equals : eq
!= : not equals :ne
重写魔法方法
#代码 1: 比较两个人的年龄大小
class Person:
"""人"""
def __init__(self,name,age):
self.name = name
self.age = age
def __ge__(self,other):
#判断大小
if self.age >= other.age
return True
return False
def __gt__(self,other):
if self.age > other.age:
return False
def __eq__(self,other):
if self.name == other.name and self.age == other.age:
return True
return False
p1 = Person("席少",20)
p2 = Person("小王",16)
p3 = Person("小王",16)
#比较两个人的年龄
print(p1.age > p2.age)
#模拟生活中两个人的比较,默认比较的是年龄
print(p1 >= p2)
print(p1 > p2)
print(p1 == p2)
print(p3 == p2)
set集合中是怎么判断两个数据是否重复的?
Python中的集合,再添加一个数据到集合中时,会通过__hash__()计算这个对象的哈希值,通过哈希值在集合中已经存在的数据中进行检索,如果相同哈希值的对象不存在直接添加,如果已经存在则继续调用对象的__eq__()方法判断要添加的对下哪个和已经添加的对象是否属于同一个对象,如果是同一个对象则表示数据重复不允许添加,如果不是同一个对象则允许添加。
Person自定义类型,怎么实现重复判断?
"""
需求:将自定义的用户对象数据存储到集合中,**默认身份证号码相同的用户是同一个人**。
"""
class Person:
def __init__(self,name,reg_no):
self.name = name
self.reg_no = reg_no
def __str__(self):
return f"<{self.name}>"
def __repr__(self):
return f"<{self.name}>"
def __hash__(self):
return f"<{self.name}>"
def __eq__(self,other):
if self.name == other.name and self.reg_no == other.reg_no:
return True
return False
if __name__ == "__main__":
p1 = Person("席少","101")
p2 = Person("小王","102")
p3 = Person("小张","103")
p4 = Person("小张","103")
#集合去重
s =set()
s.add(p1)
s.add(p2)
s.add(p3)
s.add(p4)
print(s)
对象数据完全复制:
深拷贝: import copy; copy.deepcopy()
source = copy.copy(target) :将target浅拷贝一份赋值给source
source = copy.deepcopy(target) :将target深拷贝一份赋值给source
反射
反射:是生活中的反射接触最多的就是光线的反射,理解的更多的是镜子,反射其实就是通过一段字符信息,得到一个对象的结果,就类似生活中女朋友给男朋友说想要一个YSL口红,到某个节日的时候确实得到了这个口红。这个过程就是反射。
代码中的反射就是通过字符串信息,得到类型中/模块中的一个Python对象
hasattr(obj,attribute) #对象obj是否包含某个指定的attribute属性
getattr(obj,attribute)
delattr(obj,attribute)
setattr(obj,attribute)
"""
反射方法:通过一个字符串,反向查询类型中是否包含指定的属性数据
"""
class Person:
def __init(self,name):
self.name = name
def eat(self,food):
print(f"{self.name}要吃饭了...{food}")
#常规调用:我们知道类型中有什么属性和方法
p = Person("席少")
print(p.name)
p.eat("红烧肉")
#反射调用:场景远程调用,不知道对方的类型中有什么属性和方法
#对方只是提供了 有name 属性,有eat()方法。具体是否包含不知道
p2 = Person("席少")
#判断对象中是否包含name属性
if hasattr(p2,"name"):
#使用name属性,通过判断的方式避免了错误的发生
print(p2.name)
#反射调用
name = getattr(p2,"name")
print(name)
总结:反射,就是通过字符串来反向得到对象的属性数据,主要应用场景就是在数据接口远程调用时不知道类型中是否包含具体的属性或者方法,通过反射的形式得到属性和方法进行执行,避免了属性和方法不存在的错误导致程序崩溃!
p3 =Person("席少")
#常规调用:不清楚Person中是否有sleep().直接调用导致程序崩溃
#p3.sleep()
#反射调用:不清楚Person中是否有sleep(),反射调用不会导致程序出现问题
if hasattr(p3,"sleep"):
p3.sleep()