Contents
7.15. 类的高级特性¶
7.15.1. super函数的执行顺序¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
class A:
def __init__(self):
print('A')
class B(A):
def __init__(self):
print('B')
super(B, self).__init__()
class C(A):
def __init__(self):
print('C')
super().__init__()
class D(B,C):
def __init__(self):
print('D')
super(D, self).__init__()
if __name__ == '__main__':
print(D.__mro__) #(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
d = D()
7.15.2. super()函数的使用¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
# auther; 18793
# Date:2019/5/10 17:53
# filename: 类的继承2.py
class Employee:
def __init__(self,salary):
self.salary = salary
def work(self):
print("普通员工正在写代码,工资是:",self.salary)
class Customer:
def __init__(self,favorite,address):
self.favorite = favorite
self.address = address
def info(self):
print("我是一个顾客,我的爱好是:{},地址是:{}".format(self.favorite,self.address))
class Manager(Employee,Customer):
#重写父类的构造方法
def __init__(self,salary,favorite,address):
print("--------Manager的构造方法------------")
#通过super()函数调用父类的构造方法
super(Manager, self).__init__(salary)
#同上面的效果一样
# super().__init__(salary)
Customer.__init__(self,favorite, address)
if __name__ == '__main__':
m = Manager(25000,"IT产品","深圳")
m.work()
m.info()
7.15.3. 对象的 自省 功能¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
class Person(object):
'''
人类
'''
name = "hujianli"
class Student(Person):
def __init__(self,school_name):
self.school = school_name
if __name__ == '__main__':
user = Student("仙剑")
print(user.__dict__) #查看类属性,自省
print(Person.__doc__)
print(Person.__dict__)
user.__dict__["school_addr"] = "北京"
print(user)
print(user.__dict__)
print(dir(user))
7.15.4. 类中实例属性的查找顺序¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
class D:
pass
class E:
pass
class C(E):
pass
class B(D):
pass
class A(B,C):
pass
#顺序:A,B,D,C,E
#__mro__,类的属性查找顺序
print(A.__mro__)
#(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)
7.15.5. isinstance()的用法¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
'''
语法:
isinstance(object, classinfo)
object 是变量,classinfo 是类型即 (tuple,dict,int,float,list,bool等) 和 class类
'''
print(isinstance(1,int))
print(isinstance(1.0,float))
print(isinstance("aa",str))
print(isinstance(1,list))
print()
print()
'''
type()与isinstance()的区别:
共同点:两者都可以判断对象类型
不同点:对于一个 class 类的子类对象类型判断,type就不行了,而 isinstance 可以。
'''
class A(object):
pass
class B(A):
pass
b = B()
print(isinstance(b,B))
print(isinstance(b,A))
print(" type ".center(100,"*"))
print(type(b) is B) #True
#b指向了B()对象,虽然A是B的父类,但是A是另外一个对象,它们的id是不相等的
print(type(b) is A) #False
7.15.6. 抽象基类¶
代码示例 1¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
#判断类是否有某种属性
#抽象基类的作用类似于JAVA中的接口。在接口中定义各种方法,然后继承接口的各种类进行具体方法的实现。
# 抽象基类就是定义各种方法而不做具体实现的类,任何继承自抽象基类的类必须实现这些方法,否则无法实例化
#抽象基类(abc模块)
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __len__(self):
return len(self.employee)
com = Company(["11", "22", "33"])
#hasattr判断类有没有某种属性,方法也是类的属性
print(hasattr(com,"__len__")) #True
#虽然用hasattr可以判断,但正确的方式是定义一个抽象基类
#我们在某些情况下希望判定某个对象的类型,可以用抽象基类
from collections.abc import Sized
print(isinstance(com,Sized)) #True
print(len(com))
代码示例 2¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
#模拟一个抽象基类
#写一个抽象基类,它的子类必须要重写抽象基类里面的方法
import abc
#定义一个抽象基类
class CacheBase(metaclass=abc.ABCMeta):
@abc.abstractclassmethod
def get(self,key):
pass
@abc.abstractclassmethod
def set(self,key,value):
pass
#子类,必须有抽象基类里面的方法,get和set
#假入不写set方法会报错
class RedisCache(CacheBase):
def get(self,key):
pass
def set(self,key,value):
pass
redis_cache = RedisCache()
抽象类与接口
#!/usr/bin/env python
# -*- coding:utf8 -*-
# @auther: 18793
# @Date: 2020/6/19 14:09
# @filename: sample.py
# @Email: 1879324764@qq.com
# @Software: PyCharm
import abc
class All_file(metaclass=abc.ABCMeta):
all_type = "file"
@abc.abstractmethod # 定义抽象方法,无需实现功能
def read(self):
""" 子类必须定义读功能"""
pass
@abc.abstractmethod
def write(self):
""" 子类必须定义写功能"""
pass
# class Txt(All_file):
# pass
#
# t1 = Txt()
class Txt(All_file): # 子类继承抽象类,必须定义read和write方法
def read(self):
print("读文本数据...............")
def write(self):
print("写文本数据...............")
class Sata(All_file): # 子类继承抽象类,必须定义read和write方法
def read(self):
print("硬盘数据的读方式..........")
def write(self):
print("硬盘数据的写方式..........")
class Process(All_file): # 子类继承抽象类,必须定义read和write方法
def read(self):
print("进程数据的读方式..........")
def write(self):
print("进程数据的写方式..........")
wenben = Txt()
yingpan = Sata()
jingcheng = Process()
wenben.read()
yingpan.write()
jingcheng.read()
print(wenben.all_type)
print(yingpan.all_type)
print(jingcheng.all_type)
抽象类本质上还是类,它指的是一组类的相似性, 包括数据属性(如all_type)和函数属性(如read、write), 而接口只强调函数属性的相似性。
抽象类是一个介于类和接口之间的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计。
7.15.7. 元类¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
# 把User类创建的过程委托给元类去做,这样代码的分离性比较好
class MetaClass(type):
def __new__(cls, *args, **kwargs):
return super().__new__(cls,*args, **kwargs)
class User(metaclass=MetaClass):
def __init__(self,name):
self.name = name
def __str__(self):
return "test"
if __name__ == '__main__':
#python中类的实例化过程,会首先寻找metaclass,通过metaclass去创建User类
my_obj = User(name="derek")
print(my_obj) #test
7.15.8. 通过type来创建类¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
print("一个简单type创建类的例子".center(100,"*"))
#type(object_or_name, bases, dict)
#type里面有三个参数,第一个类名,第二个基类名,第三个是属性
User = type("User",(),{"name":"derek"})
my_obj = User()
print(my_obj.name) #derek
print(" 使用type创建类和方法 ".center(100,"*"))
#不但可以定义属性,还可以定义方法
def say(self): #必须加self
return "i am derek"
User = type("User",(),{"name":"derek","say":say})
my_obj = User()
print(my_obj.name) #derek
print(my_obj.say()) #i am derek
print(" 让type创建的类继承一个基类 ".center(100,"*"))
def say(self): #必须加self
return "i am derek"
class BaseClass:
def answer(self):
return "i am baseclass"
#type里面有三个参数,第一个类名,第二个基类名,第三个是属性
User = type("User",(BaseClass,),{"name":"derek","say":say})
if __name__ == '__main__':
my_obj = User()
print(my_obj.name) #d erek
print(my_obj.say()) # i am derek
print(my_obj.answer()) # i am baseclass
7.15.9. 通过传入的字符串动态的创建不同的类¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
def create_class(name):
if name == 'user':
class User:
def __str__(self):
return "user"
return User
elif name == "company":
class Company:
def __str__(self):
return "company"
return Company
if __name__ == '__main__':
Myclass = create_class("user")
my_obj = Myclass()
print(my_obj) #user
print(type(my_obj)) #<class '__main__.create_class.<locals>.User'>