抽象基类(abc模块)
# 抽象基类(abc模块)
# 抽象基类(abstract base class.ABC): 抽象基类就是类里定义了纯虚成员函数的类
# 纯虚函数只是提供了接口,并没有具体实现,抽象基类不能被实例化(不能创建对象)
# 通常是作为基类供子类继承,子类中重写虚函数,实现具体的接口。
# 抽象基类就是定义各种方法而不做具体实现有类,任何继承自抽象基类
# 应用场景
# 1. 判断某个对象的类型
# 2. 我们需要强制某个子类必须实现某些方法
# 使用isinstance 和 type的区别
class Demo(object):
def __init__(self, names):
self.names = names
def __len__(self): # Sized 有__len__方法 返回True
return len(self.names)
def __iter__(self): # 查看原代码可以找到Iterable有__iter__方法 返回True
pass
def test(self):
pass
d = Demo(['ellen', 'python'])
print(len(d))
print(hasattr(d, 'test')) # 判断是否有这个方法
from collections.abc import Sized,Iterable
print(isinstance('demo', int)) # 判断类型 判断实例
print(isinstance(d,Sized))
print(isinstance(d,Iterable))
'''
2. 我们需要强制某个子类必须实现某些方法
web cache redis memcache 如果自己写了一个web框架要集成cache缓存,有redis缓存和memcache缓存
这些缓存要自己去实现,还有一个缓存基类,也就是说这个类有一些方法必须在子类中才能实现,必须要继承才能实现
'''
import abc
class CacheBase(metaclass=abc.ABCMeta):
@abc.abstractmethod
def get(self, key):
#raise ValueError
pass
@abc.abstractmethod
def set(self, key, value):
# raise NotImplementedError
pass
# self.key = key
class RedisBase(CacheBase):
# 重写父类中的方法
def get(self, key):
pass
def set(self,key,value):
pass
r = RedisBase()
#r.get('ellen')
使用isinstance 和 type的区别
# 使用isinstance 和 type的区别
# i = 1
# s = 'ellen'
# print(isinstance(1,int))
# print(isinstance(s,int))
# print(isinstance(s,str))
# print(type(i))
# if isinstance(i,int): # 返回123
# if type(i) == 'int': # 不会打印
# print(123)
# class A:
# pass
#
# class B(A):
# pass
# b = B()
# print(isinstance(b,B)) # True
# print(isinstance(b,A)) # True 考虑类的继承关系
#
# print(type(b) is B) # True
# print(type(b) is A) # False 没有考虑类的继承关系
# == value 是数值
# is 是内存地址
# 区别
class A:
# 类属性
aa = 1
# 实例方法
def __init__(self, x, y):
# 实例属性
self.x = x
self.y = y
# self.aa = 22 # 在外部定义a.aa = 22 相当于在内部方法添加了实例属性
a = A(1, 2)
# print(a.x, a.y, a.aa) # 可以向上查找
# print(A.x) # 报错 不能向下查找
# print(A(1,2).x) # 1 可以查找
A.aa = 11
a.aa = 22
print(a.aa) # 22
print(A.aa) # 11
b = A(1,2)
print(b.aa) # 11
super 函数
# super 函数
# 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时
# 我们就需要调用父类的方法了,可能过使用super来实现
class A:
def __init__(self):
print('A')
class B(A):
def __init__(self):
print('B')
super().__init__()
# 重写了B的构造函数 为什么还要去调用super
# super 执行顺序到底是什么样的?
b = B()
class People(object):
def __init__(self,name,age,weight):
self.name = name
self.age = age
self.weight = weight
def speak(self):
print('%s 说: 我%d岁了'%(self.name,self.age))
class Student(People):
def __init__(self,name,age,weight,grade):
# super().__init__(name,age,weight)
People.__init__(self,name,age,weight)
self.grade =grade
s = Student('ellen',18,90,3)
s.speak()
class A:
def __init__(self):
print('A')
class B(A):
def __init__(self):
print('B')
super().__init__()
class C(A):
def __init__(self):
print('C')
super().__init__()
class E:
pass
class D(B,C,E):
def __init__(self):
print('D')
super().__init__()
d = D()
print(D.__mro__) # D B C A
# super 调用父类中的方法
# 而是按照mro 算法来调用的