目录
3.8.4 析构方法
-
当整个程序脚本执行完毕后自动调用
__del__
方法 -
当对象被手动销毁时也会自动调用
__del__
-
析构函数一般用于资源回收,利用
__del__
方法销毁对象回收内存等资源
class Animals:
def __init__(self,name):
self.name = name
print("__init__构造初始化方法")
pass
def __del__(self):
print("这是析构方法")
print("当某个作用域下面,没有被使用引用的情况下,解析器会自动调用此函数")
pass
Cat = Animals("Rany")
3.8.5 继承
-
面向对象三大特征:封装、继承、多态
-
封装:是指把内容封装到某个地方,从另外一个地方去调用被封装的内容,以便于后面的使用。
-
继承:子类可以继承父类的属性和行为
3.8.5.1 单继承
对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需要继承父类而不必一一实现每个方法。
方法:class 子类(父类):
class Anmials:
def eat(self):
print("吃饭")
pass
def drink(self):
print("喝水")
pass
pass
class dog(Anmials): #继承Anmials,dog是Anmials的子类
def wwj(self):
print("汪汪叫")
pass
pass
# dog中一共有三个方法,继承自父类的eat、drink和自己wwj。
dog1 = dog()
dog1.eat()
dog1.drink()
dog1.wwj()
3.8.5.2 多继承
-
多继承就是使用一个子类去继承多个父类的方法
-
在Python3以上版本按照广度优先原则来进行查找
class A: #新建父类A
def eat(self):
print("A")
pass
pass
class B: #新建父类B
def drink(self):
print("B")
pass
pass
class C: #新建父类C
def run(self):
print("C")
pass
pass
class ABC(A,B,C): #使用ABC继承三个父类
pass
abc = ABC() #创建实例
abc.eat() #实例化对象
abc.drink()
abc.run()
3.8.5.3 继承的传递
类的传递过程中,我们把父类称为基类,子类称为派生类,父类的属性和方法可以一级一级的传递到子类。
class A:
def foo(self):
print('called A.foo()')
class B(A):
pass
class C(A):
def foo(self):
print('called C.foo()')
class D(B, C):
pass
if __name__ == '__main__':
d = D()
d.foo()
B、C 是 A 的子类,D 多继承了 B、C 两个类,其中 C 重写了 A 中的 foo() 方法。如果 A 是经典类(如上代码),当调用 D 的实例的 foo() 方法时,Python 会按照深度优先的方法去搜索 foo() ,路径是 B-A-C ,执行的是 A 中的 foo() ;如果 A 是新式类,当调用 D 的实例的 foo() 方法时,Python 会按照广度优先的方法去搜索 foo() ,路径是 B-C-A ,执行的是 C 中的 foo() 。因为 D 是直接继承 C 的,从逻辑上说,执行 C 中的 foo() 更加合理,因此新式类对多继承的处理更为合乎逻辑。在 Python 3.x 中的新式类貌似已经兼容了经典类,无论 A 是否继承 object 类, D 实例中的 foo() 都会执行 C 中的 foo() 。但是在 Python 2.7 中这种差异仍然存在,因此还是推荐使用新式类,要继承 object 类。
3.8.6 父类方法
3.8.6.1 重写和调用父类方法
所谓重写就是在子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
class A:
def foo(self):
print('called A.foo()')
class C(A): #继承父类
def foo(self): #重写父类方法
print('called C.foo()')
ranys=A() #调用父类方法
ranys.foo()
rany=C() #调用子类方法
rany.foo()
3.8.7 多态
-
所谓多态就是定义时的类型和运行时的类型不一样,此时就称为多态。不同子类的对象有不同的行为表现。
-
实现多态的前提:
-
必须发生在父类的子类之间
-
重写
-
-
特点
-
只关心对象的实例方法是否同名,不关心对象所属的类型;
-
对象所属的类之间,继承关系可有可无;
-
多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性比较强;
-
多态是调用方法的技巧,不会影响到类的内部设计。
-
#对象所属的类之间有继承关系(应用更广)
class gradapa(object):
def __init__(self, money):
self.money = money
def p(self):
print("this is gradapa")
class father(gradapa):
def __init__(self, money, job):
super().__init__(money)
self.job = job
def p(self):
print("this is father,我重写了父类的方法")
class mother(gradapa):
def __init__(self, money, job):
super().__init__(money)
self.job = job
def p(self):
print("this is mother,我重写了父类的方法")
return 100
# 定义一个函数,函数调用类中的p()方法
def fc(obj):
return obj.p()
gradapa1 = gradapa(3000)
father1 = father(2000, "工人")
mother1 = mother(1000, "老师")
fc(gradapa1) # 这里的多态性体现是向同一个函数,传递不同参数后,可以实现不同功能.
fc(father1)
print(fc(mother1))
3.8.7.1 类属性和实例属性
-
类属性概念:就是了哦对象所拥有的属性,他被所有类对象的实例对象所共有,类对象和实例对象都可以访问
-
实例属性的概念:实例属性所拥有的属性,只能通过实例对象访问
class Student:
name = "Rany" #类属性,属于类的属性,就是Student的属性
def __init__(self,age):
self.age=age #实例属性
pass
pass
Ran = Student(19)
print(Ran.name) #访问类属性
print(Ran.age) #访问实例属性
print(Student.name) #;类属性是可以被类对象和实例对象共同访问使用的,实例属性只能由实例对象访问
# print(Student.age) #这个不能被访问
3.8.7.2 类方法和静态方法
类方法的概念
类对象所拥有的方法,需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,类方法可以通过类对象,实例对象调用。
class People:
country = "china"
#类方法 用 classmethod
@classmethod
def get_country(cls):
return cls.country #访问类属性
pass
pass
print(People.get_country()) #通过类对象去引用
p = People()
print("实例对象访问%s"%p.get_country())
静态方法
-
静态方法需要用到修饰器 @ staticmethod 来标识,告诉解释器这是一个静态方法
-
通过类名调用静态方法
#语法:
@staticmethod
def 静态方法名():
pass
#举例
class Student:
company = "js" #类属性
@staticmethod
def add(a,b): #静态方法
print("{0}+{1}={2}".format(a,b,(a+b)))
return a++b
pass
Student.add(10,20)