目录
析构方法
当一个对象被删除或者被销毁时,python解释器也会默认调用一个方法,这个方法为__del__()方法,也称为析构方法。
class Animal:
def __init__(self,name):
self.name=name
print('这是构造初始化方法')
pass
def __del__(self):
#主要的应用就是来操作对象的释放,一旦释放完了,对象便不能使用
print('当在某个作用域下面,没有被使用【引用】的情况下,解释器会自动调用此函数来释放内存空间')
print('这是析构方法')
print('%s这个对象被彻底清理了,内存空间也释放掉了'%self.name)
pass
cat=Animal('小花猫')
del cat#手动清理删除对象,会执行del函数
# print('*'*40)
# dog=Animal('柯基小狗')
继承
在python中展现面向对象的三大特征: 封装、继承、多态
封装:指的是把内容封装到某个地方,便于后面的使用,他需要把内容封装到某个地方从另外一个地方去调用被封装的内容。
对于封装来说,其实就是使用初始化构造方法将内容封装到对象中,然后通过对象直接或者self来获取被封装的内容。
继承: 和现实生活当中的继承是一样的:也就是 子可以继承父的内容【属性和行为】(爸爸有的儿子都有,相反 儿子有的爸爸不一定有,所以对于面向对象的继承来说 其实就是将多个类共有的方法提取到父类中 子类仅需继承父类而不必一一去实现,这样就可以极大的提高效率 减少代码的重复编写,精简代码的层级结构便于拓展。
多态在下面介绍。
单继承:
class Animal:
def eat(self):
print('吃饭了')
pass
def drink(self):
pass
pass
class Dog(Animal): #继承Animal父类,Dog为子类
def wwj(self):
'''
子类独有的
:return:
'''
print('小狗汪汪叫')
pass
class Cat(Animal):
def mmj(self):
print('小猫喵喵叫')
pass
d1=Dog()
d1.eat() #具备了吃的行为
print('*********cat的行为************')
c1=Cat()
c1.eat()
多继承:
class shenxian:
def fly(self):
print('神仙会飞')
pass
pass
class Monkey:
def chitao(self):
print('猴子喜欢吃桃')
pass
pass
class Sunwukong(shenxian,Monkey): #继承了多个类
pass
swk=Sunwukong()
swk.fly()
swk.chitao()
当多个父类存在相同的方法时,应该调用那一个?我们举例说明
class D(object):
def eat(self):
print('D.eat')
pass
pass
class C(D):
def eat(self):
print('C.eat')
pass
pass
class B(D):
pass
class A(B,C):
pass
a=A()
a.eat() #C.eat 在执行eat的方法时,查找方法的顺序:A去B中若B中没有去C中查找 如果C类中没有则去D类查找,如果还没找到就会报错
print(A.__mro__)#可以显示类的依次继承关系
可以发现,在执行eat的方法时,查找方法的顺序:A去B中若B中没有去C中查找 如果C类中没有则去D类查找,如果还没找到就会报错。
间接继承:
class Grandfather:
def eat(self):
print('吃的方法')
pass
pass
class Father(Grandfather):
# def eat(self):#因为父类中已经存在这个方法,在这里相当于方法重写【方法覆盖了】
# print('爸爸经常吃海鲜')
pass
class Son(Father):
pass
son=Son()
print(Son.__mro__)
son.eat()#此方法时从Grandfather继承过来的
重写和调用父类的方法
所谓重写,就是子类中,有一个和父类名字相同的方法,在子类中的方法会覆盖掉父类中同名的方法。
为什么要重写:父类的方法不满足子类的需要,那么子类就可以重写父类或者完善父类。
class Dog:
def __init__(self,name,color):
self.name=name
self.color=color
pass
def bark(self):
print('旺旺叫...')
pass
pass
class kejiquan(Dog):
def __init__(self,name,color): #重写父类的方法
#针对这种需求,我们就需要去调用父类的函数了
#Dog.__init__(self,name,color) #手动调用父类的方法,执行完毕,就可以具备name和color这俩个实例属性
super().__init__(name,color)#super是自动的找到父类进而调用方法,假设继承了多个父类,那么会按照顺序逐个的去找,然后再调用
#扩展其他的属性
self.height=90
self.weight=20
pass
def __str__(self):
return '%s是%s,升高是%d,体重是%d'%(self.name,self.color,self.height,self.weight)
def bark(self): #属于重写父类的方法
super().bark()#调用父类方法
print('叫的跟神一样')
print(self.name)
pass
pass
kj=kejiquan('柯基犬','红色')
kj.bark()
print(kj)
代码中用调用父类的方法。当在子类中有一个方法需要父类的功能,并且又要添加新的功能。如果直接重写父类方法,那么就要重复写很多代码。那么这就要调用父类方法,调用父类就是把父类的功能调用过来。
多态
多态:顾名思义就是多种状态、形态,就是同一种行为 对于不同的子类【对象】有不同的行为表现。
要想实现多态 必须的有两个前提需要遵守:
1、继承:多态必须发生在父类和子类之间
2、重写: 子类重写父类的方法
多态有什么用:
增加程序的灵活性
增加程序的拓展性
#案例演示
class Animal:
'''
父类
'''
def say_who(self):
print('我是一个动物...')
pass
pass
class Duck(Animal):
def say_who(self):
print('我是一只鸭子')
pass
class Dog(Animal):
def say_who(self):
print('我是一只小狗')
pass
pass
class Cat(Animal):
def say_who(self):
print('我是一只小猫')
pass
pass
class Bird(Animal):#新增鸟类
def say_who(self):
print('我是一个鸟')
pass
pass
class People():
def say_who(self):
print('我是人类')
pass
pass
class student(People):
def say_who(self):
print('我是一年级的张明')
pass
pass
def commonInvoke(obj):
'''
统一调用的方法
:param obj:对象实例
:return:
'''
obj.say_who()
# duck1=Duck()
# duck1.say_who()
# dog=Dog()
# dog.say_who()
# cat=Cat()
# cat.say_who()
listObj=[Duck(),Dog(),Cat(),Bird(),student()]
for itme in listObj:
'''
循环调用函数
'''
commonInvoke(itme)
类方法和静态方法
属性:类属性和实例属性
类属性就是类对象所拥有的属性
class Student:
name='李明' #属于类属性,就是student类对象所拥有的
def __init__(self,age):
self.age=age #实例属性
pass
pass
Student.name='李易峰'#通过类对象修改数据,因为name的所有权属于类对象
lm=Student(18)
print(lm.name) #通过实例对象去访问类属性
print(lm.age)
print('-----------xh数据-----------------------')
xh=Student(28)
print(xh.name)
print(xh.age)
print('--------------通过类对象访问name------------')
print(Student.name) #类名.属性名去访问
通过上述,可以发现
1.类属性是可以被类对象和实例对象共同访问使用的
2.实例属性只能由实例对象访问
3.通过实例对象没法修改类属性
类方法:类对象所拥有的方法,需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,类方法可以通过类对象,实例对象调用。
类对象所拥有的方法,需要用@staticmethod来表示静态方法,静态方法不需要任何参数。
class People:
country='china'
@classmethod #类方法需要用classmethod来进行修饰
def get_country(cls):
return cls.country #访问类属性
pass
@classmethod
def change_country(cls,data):
cls.country=data #在类方法中修改类属性的值
pass
@staticmethod #静态方法 不需要传入参数
def getData():
return People.country #通过类对象去引用
@staticmethod
def add(x,y):
return x+y
pass
print(People.get_country()) #通过类对象去引用
p=People()
print(p.get_country())#实例对象访问
print('修改之后的数据')
People.change_country('英国')
print(People.get_country())
print(People.add(10,56)) #带参数的静态方法
一般情况下,我们不会通过实例对象去访问静态方法。
为什么要使用静态方法呢
1.由于静态方法注意来存放逻辑性代码,本身和类以及实例对象没有交互,也就是说,在静态方法中,不会设计到类中属性和方法的操作
2.数据资源能够得到有效的充分利用
import time #引入时间模块
class Timetest:
def __init__(self,hour,min,second):
self.hour=hour
self.min=min
self.second=second
@staticmethod
def showTime():
return time.strftime("%H:%M:%S",time.localtime())
pass
print(Timetest.showTime())
t=Timetest(2,10,22)
print(t.showTime()) #没有必要通过这种方法访问静态方法
从方法定义的形式可以看出来
1.类方法的第一个参数是类对象 cls 进而去引用类对象的属性和方法 必须用装饰器 @classmethod来修饰
2.实例方法的第一个参数必须是self,通过这个self 可以去引用类属性或者实例属性,若存在相同名称实例属性和类属性的话,实例属性的优先级最高
3.静态方法不需要定义额外的参数,若是要引用属性的话 则可以通过类对象或者是实例对象去引用即可 必须用装饰器 @staticmethod来修饰