在Python中,面向对象编程的特点在于,它具有封装、继承和多态三大特性。通过高度封装性、灵活的继承性和强大的多态性,可以使程序更加高效、结构清晰,并方便管理和扩展。
类的继承
面向对象中的继承和现实生活中的继承相同,比如儿子继承父亲的财产等。面向对象中的继承是指一个类可以从另一个类中继承属性和方法。继承是一种创建新的类的方式,新创建的类叫子类,继承的类叫父类、超类、基类。继承允许子类继承父类的属性和方法,并且可以在子类中添加新的属性和方法,或者修改继承的属性和方法。
Python中定义子类的语法如下:
class 子类名(父类名1,父类名2):
语法块
在子类的定义中,可以在子类名后的圆括号中指定要继承的父类。如果有多个父类,父类名之间用逗号隔开。
动手练一练:
# 定义一个名为Person的类
class Person:
# 初始化函数(构造函数)
def __init__(self, name):
self.name = name # 将传入的参数赋值给类的属性name
def say(self): # 定义成员方法
print("你好!我是", self.name)
class Student(Person):
pass
student = Student("张三")
student.say()
执行以上代码,输出结果为:
你好!我是 张三
上面的例子中,在Person类中我们定义了name属性和say()方法,但是在Student类中什么都没有定义。由于Student是从Person继承下来的子类,所以Student同样拥有name属性和say()方法。上面的例子中可以看出,继承允许子类重用父类的代码,从而减少了代码的重复性。我们可以继续定义Child,Boy等子类并从Person继承name属性和say()方法,大大减少了代码量。
这里需要注意的是,如果子类中定义了自己的构造方法,那么父类的构造方法“_init_”就不会自动调用。需要在子类的构造方法中用super函数专门调用。例如:
动手练一练:
# 定义一个名为Person的类
class Person:
# 初始化函数(构造函数)
def __init__(self, name):
self.name = name # 将传入的参数赋值给类的属性name
def say(self): # 定义成员方法
print("你好!我是", self.name)
class Student(Person):
def __init__(self):
print("你好!我是学生")
student = Student("张三")
student.say()
执行以上代码,输出结果为:
TypeError: __init__() takes 1 positional argument but 2 were given
上面的例子中,Python解释器输出错误信息“类型错误:_init_()采用1个位置参数,但给出了2个”。说明“Person”类中的构造方法“_init_()”没有被执行,我们可以在“Student”类的构造方法中用super()函数专门调用。例如:
动手练一练:
# 定义一个名为Person的类
class Person:
# 初始化函数(构造函数)
def __init__(self, name):
self.name = name # 将传入的参数赋值给类的属性name
def say(self): # 定义成员方法
print("你好!我是", self.name)
class Student(Person):
def __init__(self):
super(Student, self).__init__("张三")
student = Student()
student.say()
执行以上代码,输出结果为:
你好!我是 张三
上面的例子中,在“Student”类的构造方法中用super()函数专门调用父类的构造方法之后运行正常。
还有一点需要注意的是,子类不能继承父类中的私有属性和方法,也不能在自己的方法内部访问父类的私有属性和方法。例如:
动手练一练:
# 定义一个名为Person的类
class Person:
# 初始化函数(构造函数)
def __init__(self, name):
self.__name = name
def __say(self):
print("这是__say私有方法")
def say(self):
self.__say()
print("这是私有属性", self.__name)
class Student(Person):
def __init__(self):
super(Student, self).__init__("张三")
def call(self):
self.__say() # 错误
student = Student()
student.say() # 输出 “这是__say私有方法”和“这是私有属性 张三”
student.call() # 错误
执行以上代码,输出结果为:
这是__say私有方法
这是私有属性 张三
AttributeError: 'Student' object has no attribute '_Student__say'
上面的例子中,Python解释器输出错误信息“属性错误:‘Student’对象没有属性‘_Student__say’”,但是成功继承了父类中say()方法,说明在子类中是不能继承父类的私有属性和方法的,但是私有属性和方法可以在同一个类中被调用。
Python中类的继承还可以一级接着一级地往下继承,就好比从爷爷到爸爸、再到儿子这样的继承关系。而任何类,最终都可以追溯到根类“object”,这些继承关系看上去就像一颗倒着的树。