一、在子类派生的新方法中重用父类功能的方式二
super()方法:调用super(自己的类名,self)会返回一个特殊的对象,super(自己的类名,self).属性,会参照属性发起者类的mro列表去当前所在类的父类中查找属性。
# 在python3中,会自动帮你添加super需要的两个默认参数,可省略为super()
class Student(People):
def __init__(self,name,age,gender,stu_id,course):
# super(Student,self).__init__(name,age,gender)
super().__init__(name,age,gender)
self.stu_id = stu_id
self.course = course
两个小练习,加深super的查找顺序:
class A:
def test(self):
super().test()
class B:
def test(self):
print('from B')
class C(A,B):
pass
c=C()
print(C.mro())
c.test()
--------------------
'''
问:是否会报错?
答案:不会报错,因为属性的查找发起者是C不是A,C的mro列表中,查找顺序为C-A-B,所以A中没有会去B中找,能找到。
虽然A与B没有继承关系,但是因为发起者是C,虽然在A中才使用super方法,但依然会去B中找
'''
class A:
def test(self):
print('A---->test')
super().aaa()
class B:
def test(self):
print('B---->test')
def aaa(self):
print('B---->aaa')
class C(A,B):
def aaa(self):
print('C----->aaa')
c=C()
print(C.mro())
c.test()
------------------------
'''
问:结果是什么?
答案:
A---->test
B---->aaa
查找顺序是按照查找发起者的mro列表,但是在super查找时,会从当前类的下一个类中找,在本题中,supper在A中,根据mro列表,查找顺序为C-A-B-Object,所以去B中找到了
'''
练习三,加深super()所传对象理解,我们知道super()自动帮我们传了super(自己的类名,self)
class A:
def x(self):
print('run A.x')
super().x()
print(self)
class B:
def x(self):
print('run B.x')
print(self)
class C(A,B):
def x(self):
print('run C.x')
super().x()
print(self)
C().x()
二、组合(表达了什么有什么的关系)
组合:把另外一个类的对象赋值给当前对象的属性
class Teacher:
def __init__(self, name, age, gender, level):
self.name = name
self.age = age
self.gender = gender
self.level = level
def tell(self):
print("%s:%s" % (self.name, self.age))
class Student:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Course:
def __init__(self, name, price, period):
self.name = name
self.price = price
self.period = period
def tell(self):
print('<%s:%s:%s>' % (self.name, self.price, self.period))
tea1 = Teacher("egon", 18, "male", 10)
stu1 = Student("xxx", 19, "male")
python = Course("python开放", 30000, "3mons")
linux = Course("linux课程", 30000, "3mons")
tea1.courses = [python,linux]
stu1.course = python
三、多态
多态:同一种事物有多种形态
例如:动物就有多种形态,如人,猫,狗等
特性,我们可以在不考虑某一个对象的具体类型情况下直接使用对象
举例:事物有多个形态
利用abc模块下的abstractmethod,可以强制继承了本类的子类必须实现本类的方法。可以只写一个pass,但必须要写这个方法
import abc
class File(metaclass=abc.ABCMeta): #同一类事物:文件
@abc.abstractmethod
def click(self):
pass
class Text(File): #文件的形态之一:文本文件
def click(self):
print('open file')
class ExeFile(File): #文件的形态之二:可执行文件
def click(self):
print('execute file')
应用:
# 假设我们已经定义了People,Dog,Pig三个类
peo=People()
dog=Dog()
pig=Pig()
#peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk()
#更进一步,我们可以定义一个统一的接口来使用
def func(obj):
obj.talk()
若想通过父类控制子类:
'''
通过abc模块,我们可以控制子类必须实现父类的方法,若无父类的方法就会报错。
'''
# 父类有的功能,子类一定有
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def speak(self):
pass
@abc.abstractmethod
def run(self):
pass
# Animal() # Animal的作用是用来制定标准的
class People(Animal):
def speak(self):
print("啊啊啊啊")
def run(self):
print("咻咻咻...")
class Dog(Animal):
def giao(self):
print("汪汪汪")
class Pig(Animal):
def heheng(self):
print("哼哼哼")
peo1=People()
d1=Dog()
p1=Pig()
peo1.jiao()
d1.giao()
p1.heheng()
此时的Animal类是无法实例化的,此时的作用仅仅是为了制定标准。虽然我们通过父类对子类施加了编写限制,但是此时Animal类仅仅只是为了制定标准而存在,我们付出了继承一个类的代价,然而我们完全可以自己私下约定好,每个类中必须有的标准,同样能够实现这个效果,所以更推荐私下约定,因为继承越多,程序的耦合就越重。
自己私下约定好,减少耦合,就是鸭子类型
四、python一切皆对象
python当中使用的所有方法,都是实例化出来的方法,也就是对象,我们在pycharm中使用方法时,代码提示会有一个self的参数,其实就是对象,从我们学习python开始,就在使用对象。对于python一切皆对象的文章有很多,也有很多的例子,长篇大论容易使人搞懵。其实在我们了解了对象之后,就可以理解我们之前使用的python内置方法的原理了。
五、面向对象高级(就是一堆内置方法)
可前往该博客查看常用的方法:
https://www.cnblogs.com/linhaifeng/articles/6204014.html
六:反射
反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
对于任意一个类,都可以知道这个类的所有属性和方法;
对于任意一个对象,都能够调用他的任意方法和属性。
这种动态获取程序信息以及动态调用对象的功能称为反射机制。
在python中实现反射非常简单,在程序运行过程中,如果我们获取一个不知道存有何种属性的对象,若想操作其内部属性,可以先通过内置函数dir来获取任意一个类或者对象的属性列表,列表中全为字符串格式
class People:
def __init__(self,name,age,gender):
self.name=name
self.age=age
self.gender=gender
obj=People('egon',18,'male')
dir(obj) # 列表中查看到的属性全为字符串
------------------
[......,'age', 'gender', 'name']
接下来就是想办法通过字符串来操作对象的属性了,这就涉及到内置函数hasattr、getattr、setattr、delattr的使用了(Python中一切皆对象,类和对象都可以被这四个函数操作,用法一样)
lass Teacher:
def __init__(self,full_name):
self.full_name =full_name
t=Teacher('Egon')
# hasattr(object,'name')
hasattr(t,'full_name') # 按字符串'full_name'判断有无属性t.full_name
# getattr(object, 'name', default=None)
getattr(t,'full_name',None) # 等同于t.full_name,不存在该属性则返回默认值None
# setattr(x, 'y', v)
setattr(t,'age',18) # 等同于t.age=18
# delattr(x, 'y')
delattr(t,'age') # 等同于del t.age