30 天学习 Python 👨‍💻 - 第 10 天 - OOP 缺失的部分

2025-06-04

30 天学习 Python 👨‍💻 - 第 10 天 - OOP 缺失的部分

昨天我几乎探索了所有关键的面向对象编程 (OOP) 概念。今天我学习了面向对象编程 (OOP) 概念的剩余部分及其在 Python 中的实现。此外,我还尝试添加一些实际的代码练习,这些练习涉及 Python 中 OOP 概念的整体使用,以便回忆起已构建的思维模型中的所有概念。

极好的()

super是 Python 中的保留字(在 Python v 2.2 中引入),在继承过程中起作用。当子类或子类继承自父类并需要调用父类的方法时,它会使用super。我知道这听起来有点令人困惑。这里有一个例子

  • 不使用super
class Employee:
  def __init__(self, name):
    self.name = name
    print(f'{self.name} is an employee')

class Manager(Employee):
  def __init__(self, department, name):
    self.department = department
    self.name = name
    Employee.__init__(self, name)
    print(f'Manager, {self.department} department')

staff_1 = Manager('HR', 'Andy')
# Andy is an employee
# Manager, HR department
Enter fullscreen mode Exit fullscreen mode

这里,__init__通过显式使用父类名称来调用父类的构造函数方法,然后self将对象作为第一个参数传递。

  • 使用super(紧凑语法 - 无需传递self
class Employee:
  def __init__(self, name):
    self.name = name
    print(f'{self.name} is an employee')

class Manager(Employee):
  def __init__(self, department, name):
    self.department = department
    self.name = name
    super().__init__(name)
    print(f'Manager, {self.department} department')

staff_1 = Manager('HR', 'Andy')
# Andy is an employee
# Manager, HR department
Enter fullscreen mode Exit fullscreen mode

就像上面代码中所示的构造函数方法一样,可以在子类内部使用以下方法调用父类的任何方法super()

在 JavaScript 中,语法更紧凑,super类似于super(parameter)。但我也喜欢 Python 的语法。它__init__使用 来调用方法更加明确super

内省

Python 能够在运行时评估对象的类型(Python 中的一切都是对象)。这意味着解释器能够在运行时动态地理解对象的属性和方法以及它们的可访问性。这被称为自省

Python 提供了一个内置函数dir来自省对象。

class Developer:
  def __init__(self, name, language):
    self.name = name
    self.language = language

  def introduce(self):
    print(f'Hi! I am {self.name}. I code in {self.language}')

dev = Developer('Matt', 'Python')

print(dir(dev)) # Try this in any Python REPL
Enter fullscreen mode Exit fullscreen mode

邓德方法

在 Python 中,可以通过定义一些称为dunder 方法的神奇方法,使类更加强大。dunder 是double-under 的简称。这些方法以双下划线作为前缀和后缀__。这些特殊方法是 Python 中针对特定用例预定义的。例如,我们能够访问内置函数,因为它被定义为一种特殊的 dunder 方法__len__

创建类时,这些 dunder 方法可用于模拟内置类型的行为。

class Sentence:
  words = []

  def add_word(self, word):
    self.words.append(word)

  def __len__(self):
    return len(self.words)

new_sentence = Sentence()
new_sentence.add_word('Hello')
new_sentence.add_word('World')
print(len(new_sentence))
Enter fullscreen mode Exit fullscreen mode

len我修改了 Sentence 类,以便我们可以使用默认不可用的内置方法来实现自定义逻辑。Dunder 方法看起来相当方便!

多重继承

一个类可以通过多重继承从多个类继承属性和方法。这是一个强大的概念,但也有一些注意事项。与 JavaScript 相比,JavaScript 不支持多重继承。

class Batsman:
  def swing_bat(self):
    return 'What a shot!'

class Bowler:
  def bowl_bouncer(self):
    return 'What a bouncer!'

class AllRounder(Batsman, Bowler):
  pass

player = AllRounder()

print(player.bowl_bouncer()) # What a shot!
print(player.swing_bat()) # What a bouncer!
Enter fullscreen mode Exit fullscreen mode

当父类具有需要初始化的构造函数方法时,情况可能会变得有点复杂。在子类中,所有继承的类构造函数方法都需要初始化。

class Batsman:
  def __init__(self, hitting_power):
    self.hitting_power = hitting_power

  def swing_bat(self):
    return f'Shot with power {self.hitting_power}'

class Bowler:
  def __init__(self, delivery_speed):
    self.delivery_speed = delivery_speed

  def bowl_bouncer(self):
    return f'Bowled with speed of {self.delivery_speed} kmph'

class AllRounder(Batsman, Bowler):
  def __init__(self, hitting_power, delivery_speed):
    Batsman.__init__(self, hitting_power)
    Bowler.__init__(self, delivery_speed)

player = AllRounder(90, 80)
print(player.swing_bat())
print(player.bowl_bouncer())
Enter fullscreen mode Exit fullscreen mode

方法解析顺序

方法解析顺序(简称 mro)是 Python 中属性和方法的继承顺序。

从多个类继承时,属性和方法将由特定层次结构的子类继承。Python 中实现此功能的底层算法使用深度优先搜索算法

class Employee:
  secret_code = 'secret'

class Manager(Employee):
  secret_code = 'm123'

class Accountant(Employee):
  secret_code = 'a123'

class Owner(Manager, Accountant):
  pass

person = Owner()
print(person.secret_code) # m123
Enter fullscreen mode Exit fullscreen mode

为了了解继承的顺序,Python 提供了一个mro可以在对象上调用的方法来查看继承的层次结构

print(Owner.mro()) # try in a python console with above code to see the result
Enter fullscreen mode Exit fullscreen mode

多重继承可能难以理解,因此这种模式在实践中并不常用。这是我在几篇文章中读到的。

今天就到这里!

终于完成了 Python 中面向对象编程的概念。我的目标是,等这次挑战结束后,在构建真正的 Python 项目时,将这些原则付诸实践。

我希望我能够涵盖 Python 中所有关键的面向对象编程概念,并以不太复杂的方式分享它。

我正在观看的视频
Python 创始人的口述历史

明天我们将深入探讨Python 中的函数式编程。这肯定会非常精彩。虽然 Python 总体来说是一种过程式语言,并且以其面向对象的概念而广受欢迎,但本周剩余时间我们将探索如何在 Python 中实现函数式编程的概念。

祝你一切顺利!

文章来源:https://dev.to/arindamdawn/30-days-of-python-day-10-oop-missing-pieces-29fl
PREV
我使用 Webcrumbs 和 GitHub Copilot 构建了一个照片编辑应用程序🔥
NEXT
使用 Javascript 操作 DOM - 如何选择节点(第 1 部分)👨🏼‍🔬🎯