概念:
继承是面向对象编程的核心特性之一,它允许一个类(子类/派生类)继承另一个类(父类/基类)的属性和方法,从而建立类之间的父子关系。通过继承,子类可以复用父类的功能,同时还能扩展或修改父类的行为。
语法:
class 子类名(父类名):
# 子类的代码块
pass
子类仅继承一个父类,形成简单的层级关系。
总结:子类可以继承父类的属性和方法,就算子类自己没有,也可以使用父类的
# 1.继承
# 就是让类和类之间转变为父子关系,子类默认继承父类的属性和方法
# 1.1 语法
# class 类名(父类名):
# 代码块
# 1.2 单继承
class Person: # 父类
def eat(self):
print('吃饭')
def sing(self):
print('唱歌')
class Girl(Person): # Person类的子类
pass # 占位符, 代码里面类下面不会写任何东西,会自动跳过,不会报错
class Boy(Person):
pass
li = Girl()
li.eat()
li.sing()
li2 = Boy()
li2.eat()
li2.sing()
# 总结:子类可以继承父类的属性和方法,就算子类自己没有,也可以使用父类的
1.子类可以继承多个父类,通过逗号分隔父类名。
2.需注意方法解析顺序(MRO)可能引发的冲突。
3.A/B/C C(子类)继承于B(父类),B类(子类)继承A类(父类),C类具有A/B类的属性和方法
4.子类拥有父类的父类的属性和方法
5.继承的传递性就是子类拥有父类以及父类的父类中的属性和方法
# 1.3 继承的传递(多重继承)
# A/B/C C(子类)继承于B(父类),B类(子类)继承A类(父类),C类具有A/B类的属性和方法
# 子类拥有父类的父类的属性和方法
class Father:
def eat(self):
print('吃饭')
def sleep(self):
print('睡觉')
class Son(Father): # Father类的子类
pass
class Grandson(Son): # Son的子类
pass
li3 = Son()
li3.eat()
li3.sleep()
li4 = Grandson()
li4.eat()
li4.sleep()
# 继承的传递性就是子类拥有父类以及父类的父类中的属性和方法
# 多继承的实际应用
class ElectricAppliance:
def power_on(self):
print("Powering on...")
class ScreenDevice:
def display(self):
print("Displaying content...")
class SmartTV(ElectricAppliance, ScreenDevice): # 组合功能
def streaming(self):
print("Streaming video...")
- 代码复用:避免重复定义相同功能。
- 扩展功能:子类可在继承基础上添加新特性。
- 接口抽象:定义基类规范,子类实现具体逻辑(如抽象类)。
- 子类会继承父类的所有公共属性和方法(私有成员需通过特殊方式访问)。
- 若子类重写父类方法,优先调用子类方法(方法覆盖)。
- 多继承时,可通过
类名.__mro__
查看方法调用顺序。
在面向对象编程中,当一个子类继承了父类的某个方法,但需要对该方法的具体实现进行修改或扩展时,可以在子类中重新定义该方法。这个过程称为方法的重写,也称为方法的覆盖。
- 方法签名必须完全相同(包括方法名、参数列表和返回类型)
- 访问权限不能比父类方法更严格
- 子类方法可以抛出比父类方法更少的异常,但不能抛出新的或更广泛的异常
- 可以使用 @Override 注解来明确标识这是一个重写方法
- 当子类需要对父类方法实现不同的行为时
- 当子类需要扩展父类方法功能时
- 当子类需要优化父类方法的性能时
# 1.4 重写指在子类中定义于父类相同名称的方法
# 1.4.1 覆盖父类方法
class Person: # 父类
def money(self):
print('一百万')
class Man(Person): # 子类
def money(self):
print('一千万')
li = Man()
li.money()
# 1.4.2 对父类方法进行扩展:继承父类的方法,子类也可以增加自己的功能
# 1.父类名.方法名(self)
class Person: # 父类
def money(self):
print('一百万')
class Man(Person): # 子类
def money(self):
Person.money(self)
print('一千万')
li = Man()
li.money()
# 2.super().方法名() --推荐使用
# super在python里面是一个特殊的类,super()是使用super类创建出来的对象,可以调用父类中的方法
class Person: # 父类
def money(self):
print('一百万')
def sleep(self):
print('睡觉')
class Man(Person): # 子类
def money(self):
super().money()
super().sleep() # 可以调用父类中的其他方法
print('一千万')
li = Man()
li.money()
# 3.super(子类名,self).方法名
class Person: # 父类
def money(self):
print('一百万')
def sleep(self):
print('睡觉')
class Man(Person): # 子类
def money(self):
super(Man,self).money()
super(Man,self).sleep()
print('一千万')
li = Man()
li.money()
- 静态方法不能被重写,只能被隐藏
- 构造方法不能被重写
- 私有方法不能被重写
- 重写方法可以使用 super 关键字调用父类的原始实现
Python中的新式类(New-style classes)是指继承自object的类,这是Python 2.2版本引入的重要改进。与经典类(旧式类)相比,新式类提供了更多功能和更好的性能。
class MyClass(object):
"""这是一个新式类"""
def __init__(self, value):
self.value = value
def display(self):
print(f"Value is: {self.value}")
必须显式继承object:在Python 2.x中,必须明确继承object类才能成为新式类;在Python 3.x中,所有类默认都是新式类
方法解析顺序(MRO):使用C3线性化算法,比经典类的深度优先搜索更合理
支持描述符协议:可以实现property、staticmethod、classmethod等高级特性
支持super()函数:可以更安全地调用父类方法
class Animal(object):
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("子类必须实现此方法")
class Dog(Animal):
def speak(self):
return f"{self.name} says: Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says: Meow!"
更好的方法解析:避免经典类在多重继承中的"钻石问题"
丰富的内置方法:支持
__slots__
、__getattribute__
等特殊方法元类支持:可以更灵活地控制类的创建过程
性能优化:新式类的属性访问等操作通常更快
# 经典类写法(Python 2.x)
class OldClass:
pass
# 新式类写法(Python 2.x)
class NewClass(object):
pass
在Python 3.x中,所有类都是新式类,即使不显式继承object。
多态是指一个对象在不同使用环境中可以表现出多种形态。具体来说,同一个方法调用由于对象的不同可能产生不同的行为,这种特性称为多态性。多态是面向对象编程的三大基本特性之一(封装、继承、多态)。
- 继承关系:必须存在类之间的继承关系(父类和子类关系)
- 方法重写:子类必须对父类的某些方法进行重写(override),即子类提供了父类方法的特定实现
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "汪汪"
class Cat(Animal):
def speak(self):
return "喵喵"
def animal_speak(animal):
print(animal.speak())
dog = Dog()
cat = Cat()
animal_speak(dog) # 输出: 汪汪
animal_speak(cat) # 输出: 喵喵
Python是动态语言,多态的实现更加灵活,不需要严格的类型声明
可以通过抽象基类(ABC)来强制子类实现特定方法
多态常与鸭子类型(Duck Typing)概念相关联
行为导向:不关注对象的具体类型,而是关注对象是否具有相同名称的方法。只要对象具有相同的方法签名,就可以被统一调用。
示例:假设有Animal类和其子类Dog、Cat,都定义了makeSound()方法。调用时不需要知道具体是Dog还是Cat,只要知道它能makeSound即可。
- 定义格式:
- class 类名:
- @staticmethod
- def 方法名(形参):
- 方法体
- 调用格式:
- 类名.方法名(实参)
- 对象名.方法名(实参)
静态方法(Static Method)是面向对象编程中一种特殊的方法类型。下面详细介绍其定义和使用方式:
class 类名:
@staticmethod # 使用装饰器声明为静态方法
def 方法名(形参1, 形参2=默认值): # 可以包含多个形参,也可以设置默认参数
"""方法的文档字符串,说明方法功能"""
方法体代码 # 通常包含与类相关但不依赖实例的操作
return 返回值 # 可选
- 不需要传入self参数
- 不能访问类属性和实例属性
- 相当于一个普通函数,只是逻辑上属于某个类
- 通过类名直接调用(推荐方式)
类名.方法名(实参1, 实参2) # 例如:MathUtils.calculate_average(85, 90)
- 通过实例对象调用(不推荐)
obj = 类名()
obj.方法名(实参) # 例如:calculator = Calculator(); calculator.add(5,3)
# 5.静态方法
# 使用@staticmethod来进行修饰,静态方法没有self,cls参数的限制
# 静态方法与类无关,可以被转换成函数使用
class Person(object):
@staticmethod # 静态方法
def study(name):
print(f'{name}会学习')
# 静态方法既可以使用对象访问,也可以使用类访问
Person.study('三笠')
li = Person()
li.study('三笠') # 调用方法时传参数
# 取消不必要的参数传递,有利于减少不必要的内存占用和性能消耗
- 静态方法无法修改类状态或实例状态
- 通常用于组织代码,将相关功能分组到类中
- 调用时无需创建类实例,节省资源
类方法(Class Method)是面向对象编程中定义在类上而非实例上的方法。它通过
@classmethod
装饰器标识,第一个参数通常命名为cls
,指向类本身而非实例。
- 访问类级属性:可以访问和修改类变量
- 无需实例化:可以直接通过类名调用,不需要创建对象实例
- 工厂模式:常用于实现替代构造函数的功能
class MyClass:
class_variable = "类变量"
@classmethod
def class_method(cls):
print(f"访问类变量: {cls.class_variable}")
return cls() # 可以返回类的新实例
当需要多种创建对象的方式时,可以使用类方法作为工厂方法:
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, date_string):
year, month, day = map(int, date_string.split('-'))
return cls(year, month, day)
# 使用类方法创建实例
date = Date.from_string("2023-11-15")
当方法需要操作类级别而非实例级别的数据时:
class Employee:
raise_amount = 1.04 # 类变量
@classmethod
def set_raise_amount(cls, amount):
cls.raise_amount = amount
# 修改所有员工的加薪比例
Employee.set_raise_amount(1.05)
类方法在继承体系中保持多态特性:
class Parent:
@classmethod
def factory(cls):
print("Parent factory")
return cls()
class Child(Parent):
@classmethod
def factory(cls):
print("Child factory")
return cls()
# 调用时会根据实际类执行相应方法
obj = Child.factory() # 输出"Child factory"
- 参数不同:类方法接收
cls
参数,静态方法无特殊参数- 继承行为:类方法可以被子类覆盖,静态方法不能
- 访问权限:类方法可以访问类状态,静态方法不能
class Example:
@classmethod
def class_method(cls):
print(f"Called from {cls.__name__}")
@staticmethod
def static_method():
print("Static method called")