一、继承
通过继承我们可以使一个类获取到其他类中的属性和方法。
在定义类时,可以在类名后面的括号中指定当前类的父类(超类、基类)。
# 定义一个动物类(Animal) 定义两个方法 run() sleep()
class Animal:
def run(self):
print('动物会跑.......')
def sleep(self):
print('动物睡觉......')
# 定义一个狗类
# 直接从Animal类中继承它的属性和方法
class Dog(Animal):
def run(self):
print('狗会跑.......')
def speak(self):
print('我会看家....')
d = Dog()
print(d)
d.run()
# 运行结果
<__main__.Dog object at 0x000001FC587B8D68>
狗会跑.......
继承提高了类的复用性,让类与类之间产生了关系,有了这个关系,才有了多态的特性。
二、⽅法重写
如果在子类中有和父类同名的方法,则通过子类实例去调用方法时,会调用子类的方法而不是父类的方法,这个特点我们称之为方法的重写(覆盖)。
class A(object):
def test(self):
print('A.........')
class B(A):
def test(self):
print('B.........')
class C(B):
def test(self):
print('C.........')
c = C()
c.test()
# 运行结果
C.........
当我们调用一个对象的方法时:
会优先去当前对象中寻找是否具有该方法,如果有则直接调用;
如果没有,则去当前对象的父类中寻找;
如果父类中有,则直接调用父类中的方法;
如果没有,则去父类中的父类寻找;
以此类推,直到找到object,如果依然没有找到就报错了。
三、super()
如果在子类中也定义了_init_()函数,那么该如何调用基类的_init_()函数?
方法一、明确指定 :
class C(P):
def __init__(self):
P.__init__(self)
print 'calling Cs construtor'
方法二、使用super()方法:
class C(P):
def __init__(self):
super(C,self).__init__()
print 'calling Cs construtor'
c=C()
super()的好处就是可以避免直接使用父类的名字,主要用于多重继承。
class A:
def m(self):
print('A')
class B:
def m(self):
print('B')
class C(A):
def m(self):
print('C')
super().m()
C().m()
如果你要改变子类继承的父类(由A改为B),你只需要修改一行代码(class C(A): -> class C(B))即可,而不需要在class C的大量代码中去查找、修改基类名。另外一方面,代码的可移植性和重用性也更高。
四、多重继承
多重继承,会使子类同时拥有多个父类,并且会获取到所有父类中的方法。
如果多个父类中有同名的方法,则会先在第一个父类中寻找,然后找第二个,找第三个…前面会覆盖后面的。
class A(object):
pass
class B(object):
def test(self):
print('B.........')
# 可以在类名后的()中添加多个类,实现多重继承
class C(A,B):
pass
# __bases__ 可以获取当前类所有的父类
print(C.__bases__)
c = C()
c.test()
# 运行结果
(<class '__main__.A'>, <class '__main__.B'>)
B.........
五、多态
同一个变量p在执行同一个方法时,由于p 指向的对象不同,因此它呈现不同的行为特征,这就是多态。
class Dog(object):
def dog_work(self):
print('狗正在工作')
class SearchDog(Dog):
def dog_work(self):
print('搜救犬正在搜索生命')
class PoliceDog(Dog):
def dog_work(self):
print('警犬正在抓坏人')
class FlyDog(Dog):
def dog_work(self):
print('飞天犬正在飞')
class BlindDog(Dog):
def dog_work(self):
print('导盲犬正在领路')
class Person(object):
def __init__(self, dog=None):
self.dog = dog
def work_with_dog(self):
self.dog.dog_work()
sd = SearchDog()
pd = PoliceDog()
fd = FlyDog()
bd = BlindDog()
p = Person(bd)
p.work_with_dog()
# 运行结果
导盲犬正在领路
当程序涉及Dog 类的dog_work方法时,该方法所需要的参数是非常灵活的,程序为该方法传入的参数只要具有指定方法就行,至于该方法呈现怎样的行为特征,则完全取决于对象本身,这就大大提高了dog_work()方法的灵活性。
六、属性和方法
类属性
直接在类中定义的属性。
类属性可以通过类或类的实例访问到,但是类属性只能通过类对象来修改,无法通过实例对象修改。实例属性
通过实例对象添加的属性。
实例属性只能通过实例对象来访问和修改,类对象无法访问修改。类方法
在类的内容以@classmethod 来修饰的方法。
类方法第一个参数是cls 也会自动被传递,cls就是当前的类对象。实例方法
在类中定义,以self为第一个参数的方法都是实例方法。
实例方法在调用时,Python会将调用对象以self传入;
实例方法可以通过类实例和类去调用;
当通过实例调用时,会自动将当前调用对象作为self传入;
当通过类调用时,不会自动传递self,我们必须手动传递self。类方法和实例方法的区别
实例方法的第一个参数是self,类方法的第一个参数是cls。
类方法可以通过类去调用,也可以通过实例调用。静态方法
在类中⽤@staticmethod来修饰的方法属于静态方法
静态方法不需要指定任何的默认参数,静态方法可以通过类和实例调用;
静态方法,基本上是⼀个和当前类无关的方法,它只是一个保存到当前类中的函数;
静态方法一般都是些工具方法,和当前类无关。Python3 类方法总结
普通方法:对象访问;
私有方法:两个下划线开头,只能在类内部访问;
静态方法:类和对象访问,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的;
类方法:类和对象访问,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的;
多继承情况下:从左到右查找方法,找到为止,不然就抛出异常。
class People:
# 定义基本属性
name=''
age=0
# 定义私有属性外部无法直接访问
__weight=0
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s say : i am %d."%(self.name,self.age))
p = People('Python',10,20)
p.speak()
# __weight无法直接访问
print(p.name,'--',p.age)#,'--',p.__weight)
单继承:
class Student(People):
grade=''
def __init__(self,n,a,w,g):
People.__init__(self,n,a,w)
self.grade = g
# 覆写父类方法
def speak():
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
class Speak():
topic=''
name=''
def __init__(self,n,t):
self.name = n
self.topic = t
# 普通方法,对象调用
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
# 私有方法,self调用
def __song(self):
print('唱一首歌自己听',self);
# 静态方法,对象和类调用,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的
@staticmethod
def song():
print('唱一首歌给类听:静态方法');
# 普通方法,对象调用
def song(self):
print('唱一首歌给你们听',self);
# 类方法,对象和类调用,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的
@classmethod
def song(self):
print('唱一首歌给类听:类方法',self)
多继承:
class Sample(Speak,Student):
a = ''
def __init__(self,n,a,w,g,t):
Student.__init__(self,n,a,w,g)
Speak.__init__(self,n,t)
test = Sample('Song',24,56,7,'Python')
test.speak()
test.song()
Sample.song()
Sample.song()
test.song()
# test.__song() 无法访问私有方法