面向对象之多态

多态:对象的多种状态 - 父类对象的多种(子类对象)状态

import abc
class People(metaclass=abc.ABCMeta):
def __init__(self, name):
self.name = name

@abc.abstractmethod
def speak(self): pass

class Chinese(People):
def speak(self):
print('说中国话')

class England(People):
def speak(self):
print('说英国话')

多态的体现:功能或是需求,需要父类的对象,可以传入父类对象或任意子类对象
注:一般都是规定需要父类对象,传入子类对象
def ask_someone(obj):
print('让%s上台演讲' % obj.name) # 父类提供,自己直接继承
obj.speak() # 父类提供,只不过子类重写了

ch = Chinese('王大锤')
en = England('Tom')

传入Chinese | England均可以,因为都是People的一种状态(体现方式)
ask_someone(ch)
ask_someone(en)

传入str不可以,因为str的对象没有name和speak
s = str('白骨精')
ask_someone(s)
p = People('kkk')

鸭子类型

需求:需要一个对象,该对象有name属性及speak方法,就可以作为一种状态的体现被传入
def ask_someone(obj):
print('让%s上台演讲' % obj.name)
obj.speak()

1.先规定:有什么属性及什么方法的类的类型叫鸭子类型
2.这些类实例化出的对象,都称之为鸭子,都可以作为需求对象的一种具体体现
class A:
# 能有自己特有的属性和方法,可以和B完全不一样,但是必须有鸭子类型规定的属性和方法,不然就不是鸭子类型
def __init__(self, name):
self.name = name

def speak(self):
print('说AAAA')


class B:
# 能有自己特有的属性和方法,可以和A完全不一样,但是必须有鸭子类型规定的属性和方法,不然就不是鸭子类型
def __init__(self, name):
self.name = name

def speak(self):
print('说BBBB')


ask_someone(B('B'))


格式化方法与析构方法
class A:
def __init__(self, name, age):
self.name = name
self.age = age

# 格式化方法:

在外界打印该类对象是被调用
# 格式化外界直接打印该类对象的字符串表示结果
def __str__(self):
# return 'abc' # 外界打印A类的对象,都打印 字符串 abc
# return super().__str__() # 系统默认的在父类中返回的是对象存放的地址信息
return '<name:%s | age:%s>' % (self.name, self.age) # 根据对象实际的属性格式化具体的输出内容

# 析构方法:

在对象被消耗的那一刹那被调用,在被消耗前可以做一些事情
def __del__(self):
# del会在self代表的对象被消耗的时候被调用
# 我们可以在析构函数中释放该对象持有的其他资源,
# 或者将一些持有资源持久化(保存到文件或数据库中)
del self.name # 也可以将name存起来

a = A('老王', 88)
print(a, type(a))

import time
time.sleep(5)

print('文件马上执行完毕,a就会被销毁')

了解

class B:
# 了解:对象.语法的【】内部实现
def __setattr__(self, key, value):
self.__dict__[key] = value # 系统默认实现,在名称空间添加名字
# self.__dict__[key] = value.lower() # 可以自定义处理一些内容

# 了了解:将对象添加属性的方式可以同字典形式
def __setitem__(self, key, value):
self.__dict__[key] = value


b = B()
# 设置
b.name = 'BBB' # 内部走的是 __setattr__
b['age'] = 18 # 内部走的是 __setitem__

# 访问
print(b.name)
print(b.age)

反射

通过 字符串 来操作类与对象的属性。
hasattr()
判断对象或者类的属性是否存在!

getattr()
获取对象或者类的属性
参数1: 对象
参数2: '属性名'
参数3: 默认值

setattr()
设置对象或者类的属性

delattr()
删除对象或者类的属性
class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr

def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
b1 = BlackMedium('阿萨斯','安达顺')
用hasattr()来判断属性是否存在
类不能判断对象的属性
print(hasattr(BlackMedium,'name')) # False
对象能判断类的属性
print(hasattr(b1,'feature')) #True

print(hasattr(b1,'name')) #True    
print(hasattr(BlackMedium,'feature')) #True
用getattr()来获取属性的值
类不能获取对象的属性的值
print(getattr(BlackMedium,'name','asd')) #asd
对象能获取类的属性的值
print(getattr(b1,'feature','asd')) #Ugly

print(getattr(BlackMedium,'feature','asd')) #Ugly
print(getattr(b1,'name','asd')) #阿萨斯
用setattr()来设置属性
没有回创建
setattr(b1, 'age', 18)
print(b1.age) # 18
有会改值
setattr(b1,'name','qwe')
print(b1.name) #qwe
用delattr()删除对象或者类的属性
print(b1.name) # 阿萨斯
delattr(b1, 'name')
print(b1.age) #18
print(b1.name) # 报错!
原文地址:https://www.cnblogs.com/wangtenghui/p/10816343.html