面向对象进阶
面向对象——多态
什么是多态?
多态是同一种事物,不同的形态
多态的目的?
多态也称为多态性,目的是为了在不知道对象具体类型的情况下,统一对象调用方法的规范(例如:名字)
多态的表现形式之一就是继承
先抽象,再继承
父类:定制一套统一的规范
子类:遵循父类的统一规范
PS:Python中不会强制限制子类必须遵循父类的规范,所以出现了抽象类
# 动物类(父类)
class Animal:
# 方法 吃
def eat(self):
pass
# 方法 叫
def spkea(self):
pass
# 猪类(子类)
class Pig(Animal):
def eat(self):
print("bia唧....")
def spkea(self):
print("哼哼哼....")
# 猫类(子类)
class Cat(Animal):
def eat(self):
print("咬ji 咬ji....")
def spkea(self):
print("喵喵喵....")
# 狗类(子类)
class Dog(Animal):
def eat(self):
print("舔ji 舔ji....")
def spkea(self):
print("汪汪汪....")
animal1 = Pig()
animal2 = Cat()
animal3 = Dog()
# 让动物们叫起来
animal1.spkea()
animal2.spkea()
animal3.spkea()
多态——抽象类
什么是抽象类?
抽象类是在Python内置的abc模块中的
抽象类的作用?
让子类必须遵循父类编写的规范
如何实现抽象类?
父类需要继承abc模块中,metaclass = abc.ABCMeta
然后在父类的方法中要装饰上abc.abstractmethod
PS:在Python中不推荐使用抽象类
PS:子类必须按照父类的方法编写规范,缺一不可。(只要父类中有几个抽象方法,子类就必须要定义几个)
import abc
# 父类
class Animal(metaclass=abc.ABCMeta):
# 方法 吃
@abc.abstractmethod
def eat(self):
pass
# 方法 叫
@abc.abstractmethod
def speak(self):
pass
# 猪类
class Pig(Animal):
def run(self):
pass
def eat(self):
print("吧唧吧唧....")
def speak(self):
print("哼哼哼....")
多态——鸭子类型
什么是鸭子类型?
鸭子类型就是不同对象,只要长得像鸭子,动作行为像鸭子,那他就是鸭子
类与类之间不用共同继承一个父类,只需要将它们做得像一种事物即可。
为什么要有鸭子类型?
不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范
所有的类,在定义时都按照统一的规范进进行编写
在Python中强烈推荐使用鸭子类型
# 猪类
class Pig:
def eat(self):
print('bia唧...')
def speak(self):
print('哼哼哼...')
# 猫类
class Cat:
def eat(self):
print('咬ji 咬ji....')
def speak(self):
print('喵喵喵...')
# 狗类
class Dog:
def eat(self):
print('舔 ji 舔ji...')
def speak(self):
print('汪汪汪...')
def SPRAK(animal):
animal.eat()
animal.speak()
dog = Dog()
cat = Cat()
pig = Pig()
SPRAK(dog)
SPRAK(cat)
SPRAK(pig)
classmethod与staticmethod装饰器
classmethod与staticmethod都是Python内置的装饰器
classmethod
classmethod是一个装饰器,给在类内部定义的方法装饰,将类内部的方法变为“类的绑定方法”
类的绑定方法:由类来调用,会将谁(类)当做第一个参数传入
staticmethod
classmethod是一个装饰器,给在类内部定义的方法装饰,将类内部的方法变为“非绑定方法”
非绑定方法:可由对象或类来调用,谁来调用都是一个普通方式
# classmethod例子
class DB:
__date = "kang is very handsome!"
def __init__(self, user, pwd, role):
self.user = user
self.pwd = pwd
self.role = role
@classmethod
def check_db(cls, user, pwd, role):
obj = cls(user, pwd, role)
if obj.user == "kang" and obj.pwd == "123" and obj.role == "admin":
print("检验通过")
print(cls.__date)
return cls.__date
# DB.check_db("kang", "123", "admin")
db_obj = DB("kang", "123", "admin")
db_obj.check_db("kang", "123", "admin")
# staticmethod例子
class Foo:
@staticmethod
def func(res):
print(res)
obj = Foo()
obj.func(123)
Foo.func(1234)
isinstance与issubclass
这两个都是Python的内置模块
isinstance:判断对象是否是另一个类的实例
issubclass:判断一个类是否是另一个类的子类
返回的都是True和False
# isinstance:判断一个对象是否是另一个对象的实例
class Foo:
pass
class Boo:
pass
foo_obj = Foo()
boo_obj = Boo()
print(isinstance(boo_obj, Boo)) # True
print(isinstance(foo_obj, Foo)) # True
print(isinstance(boo_obj, Foo)) # False
# issubclass:判断一个类是否是另一个类的子类
class Father:
pass
class Sub(Father):
pass
class Joo:
pass
print(issubclass(Sub, Father)) # True
print(issubclass(Joo, Father)) # False
面向对象高级——反射
反射是通过“字符串”对 对象属性或方法进行操作
- hasatter:通过字符串判断对象的属性或方法是否存在
- getattr:通过字符串获取对象的属性或方法,找到返回值,找不到报错(如果设置了默认值就返回默认值)
- setattr:通过字符串设置对象的属性或方法
- delattr:通过字符串删除对象的属性或方法
反射的四个方法是Python内置的
class Foo:
def __init__(self, x, y):
self.x = x
self.y = y
foo_obj = Foo(10, 20)
# hasatter:通过字符串判断对象的属性或方法是否存在
print(hasattr(foo_obj, "x")) # True
print(hasattr(foo_obj, "y")) # True
print(hasattr(foo_obj, "z")) # False
# getattr:通过字符串获取对象的属性或方法
print(getattr(foo_obj, "x")) # 10
print(getattr(foo_obj, "y")) # 20
print(getattr(foo_obj, "z", 30)) # 30
# setattr:通过字符串设置对象的属性或方法
print(setattr(foo_obj, "z", 30))
print(hasattr(foo_obj, "z")) # True
# delatter:通过字符串删除对象的属性或方法
delattr(foo_obj, "x")
print(hasattr(foo_obj, "x"))
反射的扩展例子
# 反射应用:
class FileControl:
def run(self):
while True:
# 让用户输入上传或下载功能的命令
user_input = input("请输入 上传(upload)或 下载(download)功能:").strip()
# 通过用户输入的字符串判断方法是否存在,然后调用相应的方法
if hasattr(self, user_input):
func = getattr(self, user_input)
func()
else:
print("输入有误")
def upload(self):
print("文件正在上传....")
def download(self):
print("文件正在下载....")
file_control_obj = FileControl()
file_control_obj.run()