多态
-
面向对象的三大特征:封装、继承、多态
-
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)
-
工厂模式
工厂模式是一个在软件开发中用来创建对象的设计模式。
当程序运行输入一个“类型”的时候,需要创建于此相应的对象。这就用到了工厂模式。
在如此情形中,实现代码基于工厂模式,可以达到可扩展,可维护的代 码。当增加一个新的类型,不在需要修改已存在的类,只增加能够产生新类型的子类。
代码实现:
class Car(object):
def run(self):
print("吧里吧里的跑。。。")
def stop(self):
print("蹭蹭的停车。。。")
class BMW(Car):
def run(self):
print("宝马-->>>吧里吧里的跑。。。")
def stop(self):
print("宝马-->>>蹭蹭的停车。。。")
class Benz(Car):
def run(self):
print('奔驰-->>>吧里吧里的跑...')
def stop(self):
print('奔驰-->>>蹭蹭的停车...')
class Skoda(Car):
def run(self):
print("斯柯达-->>>吧里吧里的跑。。。")
def stop(self):
print("斯柯达-->>>蹭蹭的停车。。。")
class CarFactory(object):
def new_car(self, name):
if name == "BMW":
bmw = BMW()
if name == 'Benz':
benz = Benz()
return benz
if name == 'skd':
return Skoda()
class CarStore(object):
def __init__(self, factory):
self.factory = factory
def order(self, name):
new_car = self.factory.new_car(name)
return new_car
car_factory = CarFactory()
car_store = CarStore(car_factory)
car = car_store.order('skd')
car.run()
car.stop()
- 策略模式
策略指的就是为了达到某一目的而采取的多种手段或者方法。
为了实现软件设计,对象可能会用到多种多样的算法(逻辑)。这些算法甚至会经 常改变。如果将这些算法都硬编码到对象中,将会使得对象本身变得臃肿不堪, 策略模式很好的实现了将算法与本身对象解耦,从而避免出现上述的问题。
因此策略模式可以定义为: 定义一系列算法(逻辑),将每一个算法封装起来(一 个算法创建一个类),并让它们可以相互替换。此模式让算法的变化,不会影响到 使用算法的客户
策略模式包含以下 3 个角色:
Context(环境类)
Strategy(抽象策略类)
ConcreteStrategy(具体策略类)
练习 1:假设某司维护着一些客户资料,需要在该司有新产品上市或者举行新活 动时通知客户。现通知客户的方式有两种:短信通知、邮件通知。应如何设计该 系统的客户通知部分?为解决该问题,我们先构造客户类,包括客户常用的联系 方式和基本信息,同时也包括要发送的内容。
代码实现:
# 发送方式 -- 父类
class MsgSender(object):
dst_code = '' # 联系方式
info = '' # 发送方式
# 发送内容
def send(self):
pass
# 具体发送方式-->子类
class EmailSender(MsgSender):
def send(self):
print("邮件给{}发送内容:{}".format(self.dst_code, self.info))
class PhoneSender(MsgSender):
def send(self):
print('打电话给{}发送内容:{}'.format(self.dst_code, self.info))
# 用户
class Customer(object):
name = ''
phone = ''
email = ''
send_way = None # 发送方式
def set_send_way(self, send_way):
self.send_way = send_way
def send_msg(self):
self.send_way.send()
if __name__ == '__main__':
# 创建用户
customer = Customer()
customer.email = '3501976639@qq.com'
customer.phone = '17673277948'
customer.name = 'zsc'
# 创建邮箱发送方式
email_sender = EmailSender()
email_sender.info = '欢迎看新产品'
email_sender.dst_code = customer.email
customer.set_send_way(email_sender)
customer.send_msg()
# 打电话
phone_sender = PhoneSender()
phone_sender.dst_code = Customer.phone
phone_sender.info = '欢迎看新产品'
customer.set_send_way(phone_sender)
customer.send_msg()
- 观察者模式
观察者模式:又叫发布订阅模式,定义了一种一对多的依赖关系,让多个观察者 对象同时监听某一个主题对象,这个主题对象的状态发生变化时,会通知所有观 察者对象,是他们能自动更新自己
具体应用场景: 事件驱动系统是观察者模式的例子。在这种系统中,监听者被用于监听特定事件。 监听者正在监听的事件被创建出来时,就会触发它们。这个事件可以是键入(键 盘的)某个特定键、移动鼠标或者其他。事件扮演发布者的角色,监听者则扮演 观察者的角色。在这里,关键点是单个事件(发布者)可以关联多个监听者(观 察者)
代码实现:
# 主题-->通知者 -->班长
class Monitor(object):
def __init__(self):
self.observers = [] # 保存所有观察者对象
self.status = '' # 表示状态
def attach(self, observer):
"""绑定每一个观察者"""
self.observers.append(observer)
def notify(self):
"""通知每一个观察者"""
for observer in self.observers:
observer.update()
# 观察者--> 睡觉的同学
class SleepStudentObserver(object):
def __init__(self, name, monitor):
self.name = name
self.monitor = monitor # 绑定通知者
def update(self):
print('{},{}赶快起来学习吧'.format(self.monitor.status, self.name))
if __name__ == '__main__':
monitor = Monitor()
observer1 = SleepStudentObserver('zs', monitor)
observer2 = SleepStudentObserver('lyc', monitor)
monitor.attach(observer1)
monitor.attach(observer2)
monitor.status = '老师又来了'
monitor.notify()