08. 面向对象编程(二)

这篇具有很好参考价值的文章主要介绍了08. 面向对象编程(二)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、前言

2、多重继承

2.1、潜在的问题

3、@Property

4、@staticmethod

5、运算符重载

5.1、加法运算符 + 的重载

5.2、字符串表示运算符 str() 的重载

5.3、索引运算符 [] 的重载

6、小结


1、前言

上一篇文章中,我们介绍了面向对象编程的类和实例,以及三大基本特性。今天我们继续来了解面向对象编程的其他知识。

2、多重继承

多重继承是面向对象编程中的一个概念,它允许一个类同时继承自多个父类。这使得子类可以继承多个父类的属性和方法。在Python中,多重继承是支持的,但需要小心使用,因为它可能引起一些设计上的复杂性和潜在的问题。

多重继承的场景:举个例子,我们现在可能会拥有多种角色,比如程序员(Programmer)以及老父亲(Father)。那么Python中我们可能定义两个类:

# 老父亲类
class Father:
    pass

# 程序员类
class Programmer:
    pass

同时,两个不同的类拥有一个相同的方法(eat)和各自不同的方法:老父亲拥有泡奶粉的方法,程序员需要加班改bug的方法。代码示例:

# 老父亲类
class Father:

    # 老父亲需要泡奶粉的动作
    def soak_milk(self):
        print("我是一位老父亲,加班到家后要给娃泡奶粉")

    # 老父亲也要吃饭
    def eat(self):
        print("老父亲要吃饭,吃面条")


# 程序员类
class Programmer:

    # 程序员要加班改bug
    def fix_bug(self):
        print("我是一位程序猿,需要加班改bug")

    # 程序员也要吃饭
    def eat(self):
        print("程序员要吃饭,吃快餐")

最后,我同时拥有这两个角色,那么创建一个我的类,继承了Father和Programmer,之后创建出来的实例就同时拥有了老父亲泡奶粉的能力,以及程序员加班改bug的能力。完整示例代码:

# 创建一个我的类,多重继承Father和Programmer
class Me(Father, Programmer):
    pass

# 创建一个我的实例
me = Me()
# 我要吃饭
me.eat()
# 老父亲泡奶粉
me.soak_milk()
# 程序员改bug
me.fix_bug()

执行结果:

08. 面向对象编程(二),Python,python,开发语言

从上述代码中可以看出,多重继承的语法为class 类名(父类1, 父类2...)。如果继承的多个父类中有相同的方法,那么最先执行最左继承的父类。什么?你问我怎么知道的?我猜的!!!来看我猜的对不对,Python提供了一个特殊的方法__mro__来查看类的方法解析顺序。

在多重继承中,Python 使用 C3 线性化算法来确定方法的调用顺序,这被称为方法解析顺序(Method Resolution Order,简称MRO)。MRO 定义了从多个父类中继承方法时的顺序,它是基于 C3 算法生成的线性列表。

查看结果:

08. 面向对象编程(二),Python,python,开发语言

先解析Me类,之后是Father,再Programmer。诚不欺客,没骗人吧!

2.1、潜在的问题

尽管多重继承提供了一定的灵活性,但也容易导致一些设计上的复杂性和潜在的问题,例如:

  • 菱形继承问题: 当一个子类继承自两个有共同父类的类时,可能会出现方法冲突的问题。Python 的 MRO 算法通常能够解决这个问题,但在复杂的继承结构中,需要小心设计以避免混淆。
  • 代码可读性:多重继承可能导致代码可读性降低,因为需要追踪多个父类的方法和属性。
  • 耦合性: 过度使用多重继承可能导致类之间的高度耦合,降低了代码的灵活性和可维护性。

3、@Property

@property 是 Python 中用于将方法转换为只读属性的装饰器。通过使用 @property 装饰器,你可以定义一个方法,使之在调用时表现得像一个属性一样。这有助于隐藏类的内部实现细节,提高代码的可读性。正如上一篇中提到受保护成员的访问控制时,除了使用公开方法访问外,还可以此装饰器进行访问。

class Girl:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self._weight = 90   # 女孩子的体重当然是秘密了

    def get_weight(self):
        return self._weight

girl = Girl("小花", 20)
# 访问方式1
print(f"{girl.name}今年{girl.age}岁,体重{girl._weight}公斤")
# 访问方式2
print(f"{girl.name}今年{girl.age}岁,体重{girl.get_weight()}公斤")

上面代码是前面介绍到的访问方式,除了这两个以外,还可以使用@Property。代码改造一下:

class Girl:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self._weight = 90  # 女孩子的体重当然是秘密了

    def get_weight(self):
        return self._weight


    # @Property注解装饰的,是被视为只读的属性
    @property
    def weight(self):
        return self._weight


girl = Girl("小花", 20)
print(f"{girl.name}今年{girl.age}岁,体重{girl.weight}公斤")

也是可以访问的,当我们调用girl.weight时,实际上并不是直接访问属性,而是调用get_weight()方法。使用@Property只是简化了get_weight()的调用方式。

但是值得注意的是@Property注释的属性会被视为只读属性,如果此时你试图修改它,那么Python解释器会给你抛出异常,告诉你他没有setter方法。

08. 面向对象编程(二),Python,python,开发语言

当然,如果我们已添加了@Property后,还可以使用“@属性名称.setter"方式来定义属性的setter方法。

class Girl:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self._weight = 90

    def get_weight(self):
        return self._weight


    # @Property注解装饰的,是被视为只读的属性
    @property
    def weight(self):
        return self._weight

    # 添加   @属性名称.setter   表示给该属性添加了setter方法,该setter方法允许你修改该变量的值
    @weight.setter
    def weight(self, val):
        self._weight = val


girl = Girl("小花", 20)
print(f"{girl.name}今年{girl.age}岁,体重{girl.weight}公斤")
girl.weight = 200
print(f"{girl.name}今年{girl.age}岁,体重{girl.weight}公斤")

这时候,我们运行程序就不会报错了:

08. 面向对象编程(二),Python,python,开发语言

4、@staticmethod

@staticmethod 是 Python 中用于定义静态方法的装饰器。静态方法是类中的方法,与类的实例无关,因此它不会访问或修改实例的状态。静态方法通常用于执行与类相关的操作,而不需要访问实例的属性。

class MyClass:
    @staticmethod
    def static_method_with_decorator():
        return "I am a static method with decorator"

    def static_method_without_decorator():
        return "I am a static method without decorator"

# 通过类名调用带有装饰器的静态方法
result1 = MyClass.static_method_with_decorator()
print(result1)  # 输出: I am a static method with decorator

# 通过类名调用没有装饰器的静态方法(不推荐)
result2 = MyClass.static_method_without_decorator()
print(result2)  # 输出: I am a static method without decorator

运行结果:

08. 面向对象编程(二),Python,python,开发语言

但是你会发现,其实加不加@staticmethod都允许用类名来访问静态方法,那么既然如此为什么要加上这个注解呢?其实,在 Python 中,加不加 @staticmethod 装饰器影响的是对方法的理解和类的设计风格。从功能上来说,不加 @staticmethod 也可以正常工作,因为 Python 允许通过类名直接调用类的方法。

然而,使用 @staticmethod 装饰器有一些优点:

  • 清晰性:@staticmethod 装饰器明确地表明某个方法是静态方法,提高了代码的可读性。读者可以立即看到这个方法是与类相关但与实例无关的。
  • 一致性:在类中使用 @staticmethod 保持了方法定义的一致性,使得在查看类的方法时更容易识别哪些方法是静态的。
  • IDE支持: 使用 @staticmethod 可以让一些集成开发环境(IDE)更好地支持代码提示和文档生成。

5、运算符重载

运算符重载是指在类中定义特殊方法,使得该类的实例对象可以支持一些内建运算符(如+、-、*等)的操作。通过重载运算符,我们可以定义自定义的行为,使得类对象可以与运算符一样被操作。

在Python中,运算符重载是通过特殊方法来实现的,这些方法以双下划线开头和结尾,例如 __add__、__sub__、__mul__等。以下是一些常用的运算符重载方法。

5.1、加法运算符 + 的重载

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        if isinstance(other, Point):
            return Point(self.x + other.x, self.y + other.y)
        else:
            raise TypeError("Unsupported operand type")

p1 = Point(1, 2)
p2 = Point(3, 4)
result = p1 + p2
print(result.x, result.y)  # 输出: 4 6

5.2、字符串表示运算符 str() 的重载

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"Point({self.x}, {self.y})"

p = Point(1, 2)
print(str(p))  # 输出: Point(1, 2)

5.3、索引运算符 [] 的重载

class Vector:
    def __init__(self, values):
        self.values = values

    def __getitem__(self, index):
        return self.values[index]

v = Vector([1, 2, 3, 4, 5])
print(v[2])  # 输出: 3

运算符重载为类提供了更自然和直观的使用方式,使得类的实例对象可以像内建类型一样参与各种操作。然而,需要小心不要滥用运算符重载,以避免使代码变得难以理解和维护。

6、小结

面向对象的内容远不及如此,这里只是简单介绍了最最常用的部分内容,帮助学习和入门。更多的面向对象使用还是需要结合实际项目,才会更加深入和彻底的学习掌握。今天就到这吧,一起学习,一起加油!文章来源地址https://www.toymoban.com/news/detail-814394.html

到了这里,关于08. 面向对象编程(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python 面向对象编程(2)

    前面我们介绍了 python 类和对象以及继承、私有权限,那么今天我们将来介绍 python面向对象 剩下的两大特性封装、多态,以及如何访问、修改类属性、类方法和静态方法的介绍。🚗🚗🚗 Python中的封装是一种面向对象编程的概念,它将数据和操作这些数据的方法封装到一个

    2024年02月16日
    浏览(39)
  • 【python学习】面向对象编程3

    面向过程编程:类似于工厂的流水线。 优点:逻辑清晰; 缺点:扩展性差。 面向对象编程:核心是对象二字,对象是属性和方法的集合体,面向对象编程就是一堆对象交互。 优点:扩展性强; 缺点:逻辑非常乱。 对象:属性和方法的集合体。 类:一系列相同属性和方法的

    2024年01月22日
    浏览(39)
  • 5 Python的面向对象编程

    概述         在上一节,我们介绍了Python的函数,包括:函数的定义、函数的调用、参数的传递、lambda函数等内容。在本节中,我们将介绍Python的面向对象编程。面向对象编程(Object-Oriented Programming, 即OOP)是一种编程范型,它以对象为基础,将数据和操作封装在一个类(

    2024年02月11日
    浏览(28)
  • Python系列之面向对象编程

    目录 一、面向对象编程 1.1 面向对象三大特征 1.2 什么是对象 二、类(class)和实例(instance) 2.1 类的构成 2.2 创建类 2.3 创建实例对象和访问属性 2.4 Python内置类属性 2.5 类属性与方法 三、类的继承 3.1 方法重写 四、多态 Python 系列文章学习记录: Python系列之Windows环境安装配置_开

    2024年02月08日
    浏览(32)
  • 【python学习】面向对象编程1

    流水线形式 优点:逻辑清晰 (逻辑一步一步的,是一个系统) 缺点:扩展性差 (上一个函数的输出是下一个函数的输入) 对象是什么? Python中一切皆对象 对象:就是特征和技能的结合体。 面向对象编程:定义初一个个鲜明独特的对象,然后通过对象之间的交互编程。 优

    2024年01月22日
    浏览(65)
  • Python编程学院:揭秘面向对象的魔法

    Python面向对象编程(OOP) 面向对象编程(OOP)是Python中一块强大的魔法石,它让编程变得更加直观和灵活。通过使用类和对象,你可以创建清晰的模型来代表真实世界中的事物和情景。本文将带你探索类与对象的创建、继承与多态的魔法,以及私有属性与方法和神秘的魔法方

    2024年04月11日
    浏览(39)
  • Python 面向对象编程:类、对象、初始化和方法详解

    Python 是一种面向对象的编程语言。在 Python 中,几乎所有东西都是对象,都具有其属性和方法。 类似于对象构造函数或用于创建对象的“蓝图”的类。 要创建一个类,请使用 class: 示例,创建一个名为 MyClass 的类,其中包含一个名为 x 的属性: 现在,我们可以使用名

    2024年02月08日
    浏览(46)
  • Python教程(21)——面向对象编程的三大特性

    在Python中,面向对象编程是一种核心的编程思想。Python被称为“一切皆对象”的语言,因为在Python中,几乎所有的数据都被视为对象。这包括数字、字符串、列表、函数等基本类型,还有自定义的类和对象。 Python中的面向对象编程提供了类(Class)来创建对象(Object)。类是

    2024年02月03日
    浏览(30)
  • Python基础-11 面向对象编程_各种方法

    python本身支持类的动态属性 直接使用等号=,给一个属性赋值 如果这个属性存在,则会修改该属性的值 如果这个属性不存在,则会给对象添加一个新的属性及对应的值 如果需要禁止动态添加类的属性,可以使用 __slots__ 属性,如下示例 这个属性直接定义在类中,是一个元组,用来规定

    2023年04月17日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包