多态
-
面向对象的三大特征:封装、继承、多态
-
1.封装:屏蔽实现细节,但提供对外调用方式,将功能封装为一个整体,提供简单的调用方式
-
2.继承:让类与类直接产生父子关系,子类可以拥有父类的方法和属性
-
3.多态:可以让某个类呈现多种形态
多态的三个条件
- 1.必须存在继承关系
- 2.重写目标方法
- 3.使用子类对象调用父类方法
#定义人类:可以跳舞,可以玩,在玩的过程中跳舞 #实现多态:老年人跳广场舞 class Person: """人的类型""" def dance(self): print("跳舞") def play(self): self.dance() class OldMan(Person): """老年人类型""" def dance(self): print("跳广场舞") # per1 = Person() # per1.play() old = OldMan() old.play()
-
-
用户注册案例
-
网站可以注册,注册有默认的验证码发送方式
-
分析
- 网站类
- 方法:注册方法,调用默认设备发送验证码
- 设备类
- 方法:生成验证码并发送
class WebSite: """网站类型""" def register(self,device): print("开始注册用户。。。") #调用设备发送验证码的方法 device.send("6666") input("验证码已发送,请输入:") print("注册成功") class Device: """设备类型""" def send(self,code): print("默认发送验证码:",code) #用户注册 ws = WebSite() device = Device() #发起注册 ws.register(device)
- 网站类
-
实现多态,用不同的设备注册网站,就使用相应的设备发送验证码
class WebSite: """网站类型""" def register(self,device): print("开始注册用户。。。") #调用设备发送验证码的方法 device.send("6666") input("验证码已发送,请输入:") print("注册成功") class Device: """设备类型""" def send(self,code): print("默认发送验证码:",code) class Phone(Device): """手机注册""" def send(self,code): print("通过手机发送验证码:",code) class Email: """邮箱注册""" def send(self, code): print("通过邮箱发送验证码:", code) #用户注册 ws = WebSite() # device = Device() phone = Phone() #发起注册 ws.register(phone)
实例属性和类型属性
-
-
实例属性:在实例对象中定义的属性(在
__init__
中定义的属性) -
类属性:在类中定义的属性(类里面,方法外部),多个实例对象共享一份类属性
-
实例属性的声明和访问
(1) 声明
实例属性的声明,包含在类型的
__init__
()初始化方法中,使用self关键字将属性绑定在当前对象上def __init__(self,name,age): """实例属性初始化""" self.name = name self.age = age
(2)访问
实例属性在类型内部可以通过self关键字引用,在类型外部可以通过对象引用变量访问和修改
class User: def __init__(self,name,age): """实例属性初始化""" self.name = name self.age = age user = User("zs",18) print(user.name)
-
类属性的声明和访问
(1)声明
类里面,方法外部
#数据类型 class Data: """数据类型""" courses_dict = {} #键:课程名称,值:课程对象 #使用实例对象访问 data = Data() print(data.courses_dict) #使用类对象访问 print(Data.courses_dict)
(2)访问
类属性能被当前类型的所有对象访问,或者能直接通过类型名称访问
-
修改
类属性只能被类名称引用修改,不能通过对象的引用变量修改
1.不可变类型:对象名.属性名=属性值 给对象添加属性,而不是进行修改
2.可变类型:如果对象是修改可变类型数据,是真正的修改
如果是重新给可变类型变量赋值,则是给对象添加属性
#数据类型 class Data: """数据类型""" # courses_dict = "Python" courses_dict = ["Python"] data = Data() #使用类对象修改课程为"java" # Data.courses_dict = "java" #使用实例对象访问 # print(data.courses_dict) #使用类对象访问 # print(Data.courses_dict) #使用实例对象修改课程为 "UI" # data.courses_dict = "UI" #实际上是给实例对象增加属性 #使用实例对象访问 # print(data.courses_dict) #使用类对象访问 # print(Data.courses_dict) #如果类属性为可变数据类型,则使用实例对象或者类对象都是真正的修改 # Data.courses_dict.append("java") #使用实例对象添加 # data.courses_dict.append("java") #使用实例对象访问 # print(data.courses_dict) #使用类对象访问 # print(Data.courses_dict) #实例对象给可变类型重新赋值,则是给该对象添加属性 data.courses_dict = ["Python","java"] #使用实例对象访问 print(data.courses_dict) #使用类对象访问 print(Data.courses_dict)
-
总结
类可以调用实例方法,静态方法,类方法和类属性,但是不能调用实例属性
实例对象可以调用实例方法,类方法,静态方法,类属性,实例属性
实例对象可以调用所有方法和属性,而类除了不能调用实例属性,其他的方法和属性都可以调用
class User: def __init__(self,name,age): """实例属性初始化""" self.name = name self.age = age def introduce(self): print(f"我叫{self.name},今年{self.age}岁") user = User("zs",18) # user.introduce() # User.introduce(user) print(User.name) #类对象不能调用实例属性
静态方法、类方法和实例方法
-
1、实例方法
实例方法或者叫对象,指的是在类中定义的普通方法
只有实例化对象之后才使用的方法,该方法的第一个参数接收的一定是对象本身!
class User: def introduce(self): print("这是实例方法中的代码") user = User("zs",18) #通过对象调用实例方法 user.introduce()
-
类方法:声明在类的内部,方法上使用装饰器@classmethod
第一个参数是当前类型本身,约定俗称是cls;类方法执行访问当前类型的类属性,不能访问任何对象的实例属性;类方法被当前类型调用,也能被实例对象调用
应用场景:当一个方法中只涉及到静态属性的时候可以使用类方法(类方法可以修改类属性)
class Data: student_dic = {} @classmethod def get_student_dic(cls): """获取学生信息""" return cls.student_dic @classmethod def set_student_dic(cls,stu_dic): cls.student_dic = stu_dic
-
静态方法:是被统一管理在类中的函数,声明在类的内部
1.格式:在方法添加@staticmethod
2.参数:静态方法可以有参数,页可以无参数
3.应用场景:一般用于和类对象以及实例对象无关的代码
4.使用方式:类名.方法名()(或者对象名.方法名())
import time class Views: """界面类型""" @staticmethod def get_current_time(): #获取当前时间 now = time.localtime() return time.strftime("%Y-%m-%d %H:%M:%S",now) print(Views.get_current_time())
魔术方法
-
1.构造方法
魔术方法 描述 __new__
(cls)方法创建对象 __init__
(self方法初始化对象数据 class User: def __init__(self,name,age): """实例属性初始化""" print("init方法对象初始化") self.name = name self.age = age def __new__(cls, *args, **kwargs): print("new方法开始创建对象") return object.__new__(cls) user = User("zs",18) # print(user.name) print(user)
-
对象删除方法
魔术方法 描述 __del__
()方法对象将要被删除时执行 class User: def __init__(self,name): """实例属性初始化""" print("init方法对象初始化") self.name = name def __del__(self): print("对象将要被删除") user = User("zs") print("代码执行结束") class User: def __init__(self,name): """实例属性初始化""" print("init方法对象初始化") self.name = name def __del__(self): print("对象将要被删除") def func(): user = User("zs") func() print("代码执行结束")
-
3.对象的打印
魔术方法 描述 __str__
()方法打印对象,自定义返回值(字符串) __repr__
()方法对象在组合数据类型中,打印展示自定义的返回值 -
4.对象的函数式调用
魔术方法 描述 __call__
()方法让对象可以类似函数的方法直接调用执行 class User: def __call__(self, *args, **kwargs): print("我叫张伟强,请多多关照") def introduce(self): print("我叫刘江,请多多关照") user= User() # user.introduce() user()
-
5.其他
魔术方法 描述 __eq__
()方法定义==的操作 class User: def __init__(self,name,age): self.name = name self.age = age def __eq__(self, other): # return self.age==other.age return self.__dict__==other.__dict__ def __gt__(self, other): return self.age>other.age def __cmp__(self, other): # if self.age>other.age: # return 1 # elif self.age<other.age: # return -1 # else: # return 0 return (self.age>other.age)-(self.age<other.age) user1 = User("刘江",20) user2 = User("张伟强",20) user3 = User("刘江",20) print(user1==user2) #自定义比较年龄 #自定义比较所有的属性相同,对象才相同 print(user1==user3) # == 比较的是值,is比较内存地址 lst1 = [1,2,3] lst2 = [1,2,3] print(lst1==lst2) print(lst1 is lst2)
- 1.比较两个用户对象的年龄,大于返回True小于返回False
- 2.比较两个用户对象的年龄,大于返回1,小于返回-1,相同返回0
反射方法
-
反射:通过字符串的形式操作对象相关的属性 Python中一切事物都是对象(都可以使用反射)
-
1.反射类的属性和方法 2.反射对象的属性和方法 3.反射模块中的属性和方法
反射方法 描述 hasattr(obj,name) 判断是否包含名称为name的属性 getattr(obj,name) 获取名称为name的属性的具体数据 setattr(obj,name) 较少 给名称为name属性设置value值 delattr(obj,name) 较少 删除名称为name的属性 # getattr(obj,name) 获取对象/类中的成员值 # class Teacher: # dic = {"学生信息":"show_student","老师信息":"show_teacher"} # # def __init__(self,name,age): # self.name = name # self.age = age # # @classmethod # def func(cls): # print("--func--") # # def show_student(self): # print("--show_student--") # def show_teacher(self): # print("--show_teacher--") #反射类中的属性和方法 #获取Teacher类中的dic # print(getattr(Teacher, "dic")) #获取Teacher类中的func # ret = getattr(Teacher,"func") # ret() #反射对象中的属性和方法 # teacher = Teacher("张老师",30) #获取name属性 # print(getattr(teacher, "name")) #获取所有属性 # print(getattr(teacher,"__dict__")) # ret = getattr(teacher,"show_student") # ret() #反射模块中的属性和方法 import test1 #反射模块中的属性 # print(getattr(test1,"name")) #反射模块中的方法 # func1 = getattr(test1,"func1") # func1() # func2 = getattr(test1,"func2") # func2(666) #反射模块中的类 # Person = getattr(test1,"Person") # per = Person() # per.study() # hasattr() 检测对象是否有某个成员,返回是布尔值 class Teacher: dic = {"学生信息":"show_student","老师信息":"show_teacher"} def __init__(self,name,age): self.name = name self.age = age @classmethod def func(cls): print("--func--") def show_student(self): print("--show_student--") def show_teacher(self): print("--show_teacher--") # b = hasattr(Teacher,"dic") # if b: # ret = getattr(Teacher,"dic") # print(ret) # else: # print("没有当前属性") #练习:根据用户输入的key来调用对应的方法 #如:输入"学生信息"-->"--show_student--" key = input("请输入学生或者老师信息") #学生信息 teacher = Teacher("张老师",30) b = hasattr(Teacher,teacher.dic.get(key,"")) if b: func = getattr(teacher,teacher.dic[key]) func() else: print("此方法不存在")
setattr和getattr
# setattr() 设置或者添加对象/类中的成员 class Person: pass #给Person添加静态属性age setattr(Person,"age",18) print(Person.age) #delattr 删除对象或者类中的成员 per1 = Person() setattr(per1,"name","张伟强") print(per1.name) #删除Person类中的age属性 delattr(Person,"age") print(Person.age)
单例模式
-
单例模式确保某一个类只有一个实例存在
-
当你希望在整个系统中,某个类只能出现一个实例时,就可以使用单例对象
-
方法:是否是第一次创建对象,如果是首次创建对象,则调用父类
__new__
()方法创建对象并返回 如果不是第一创建对象,直接返回第一次创建的对象即可
class Shopping: instance = None #记录创建的对象,None说明是第一次创建对象 def __new__(cls, *args, **kwargs): #第一次调用new方法,创建对象并记录 #第2-n次调用new方式时,不创建对象,而是直接放回记录的对象 #判断是否是第一次创建对象 if cls.instance==None: cls.instance = object.__new__(cls) return cls.instance else: #不是第一次创建对象 return cls.instance shop1 = Shopping() shop2 = Shopping() print(shop1,shop2) class Shopping: instance = None #记录创建的对象,None说明是第一次创建对象 def __new__(cls, *args, **kwargs): #第一次调用new方法,创建对象并记录 #第2-n次调用new方式时,不创建对象,而是直接放回记录的对象 #判断是否是第一次创建对象 if cls.instance==None: cls.instance = object.__new__(cls) return cls.instance shop1 = Shopping() shop2 = Shopping() print(shop1,shop2)