《Python高级编程》学习心得——第四章 深入类和对象
总览
鸭子类型和多态
Java中多态是通过继承实现的,子类继承父类(或接口),重写父类(或接口)的方法,从而实现多态。而在Python中,一个对象从本质上来说是一个字典的封装,在该字典中,每个key是一个属性(或方法),每个value是属性的值或者方法的实现。因此,在Python中,一个对象的类型本质上是由其属性和方法决定的,比如一个类如果实现了__next__方法和__iter__方法,那该类的对象属于迭代器类型。
下面用一个例子展示Java和Python实现多态方式的不同:
Java多态
public class Main
{
interface Animal {
public void run();
}
class Dog implements Animal {
@Override
public void run()
{
System.out.println("A dog is running");
}
}
class Cat implements Animal {
@Override
public void run()
{
System.out.println("A cat is running");
}
}
public void outerMethod()
{
Animal[] animals = new Animal[2];
animals[0] = new Dog();
animals[1] = new Cat();
for (Animal animal : animals)
{
animal.run();
}
}
public static void main(String[] args)
{
Main main = new Main();
main.outerMethod();
}
}
执行结果
A dog is running
A cat is running
Python多态
class Dog:
def run(self):
print ("A dog is running")
class Cat:
def run(self):
print ("A cat is running")
if __name__ == '__main__':
animals = (Dog(), Cat())
for animal in animals:
animal.run()
执行结果
A dog is running
A cat is running
抽象基类(abc模块)
Python的抽象基类类似于Java的接口interface的作用,但与interface不同的是,Python的抽象基类可以定义非抽象的方法。类似类方法(@classmethod)和静态方法(@staticmethod),Python中抽象方法也是用装饰器修饰定义。
视频中老师说为了避免过度设计,Python中不推荐使用抽象基类。但是通过阅读源码,我们可以发现Python源代码中使用到了抽象基类,理解抽象基类有助于我们阅读、学习Python源码。
下面用一个例子来看抽象基类的定义和使用。
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def run(self):
pass
class Dog(Animal):
"""
If class Dog does not implements abstract method run, TypeError will be raised
"""
pass
if __name__ == '__main__':
dog = Dog()
执行结果
Traceback (most recent call last):
File "AbstractClass.py", line 15, in <module>
dog = Dog()
TypeError: Can't instantiate abstract class Dog with abstract methods run
但其实用NotImplementedError也可以限制Dog类必须实现run方法,只不过Dog类仍能实例化,报错会发生在Dog类实例调用run方法时。