65.9K
CodeProject 正在变化。 阅读更多。
Home

Python 中的 OOP - 第一部分。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.69/5 (15投票s)

2014年11月24日

CPOL

6分钟阅读

viewsIcon

39621

Python 中的面向对象编程。

什么是 OOP(面向对象编程)?

面向对象编程(Object Oriented Programming)是一种编程范式,它在编程阶段创建“对象”,试图通过这种方式来模拟需要解决的问题中的实体。

“对象”包含以字段(也称为属性)形式存在的数据,并定义了操作(称为方法)。“对象”具有类型定义,在编程术语中称为类。一个“对象”是类的一个实例。

在讨论 OOP(也称为 OOP 的三大支柱)时,有 3 件关键的事情需要谈论。

  • 封装 (Encapsulation) – 指将类内部的数据和与这些数据交互的方法封装在一个单元中。这很有用,因为模型的内部结构只能通过其暴露的方法进行更改,其他实体(对象)无法修改另一个对象的内部状态。

  • 继承 (Inheritance) – 通常,当我们对现实世界的问题进行建模时,会产生大型对象层次结构。这些模型(类)之间存在相互关系。模型层次结构中的“is a”(是一个)关系在 OOP 中使用继承来实现,这意味着一个模型(或对象)中存在的特性在派生模型(或对象)中也存在。
    示例: 假设您想建立自己的网上商店并出售小工具。小工具具有属性,如电池容量、重量、内存量、操作系统等。如果您想在网上商店出售平板电脑,您可以说,平板电脑是一个小工具,当在代码中实现这些时,您可以使用继承将小工具类的所有属性和功能传递给平板电脑类。

  • 多态 (Polymorphism) – 指一个对象根据其子类型表现出不同行为的可能性。多态与继承有关。
    示例: 假设您也想在网上商店销售智能手表。一个智能手表是一个小工具。所有小工具都可以重启,这可以是小工具的一个操作(或方法)。由于平板电脑和智能手表都继承自小工具(它们之间存在 is a 关系),它们也继承了重启操作,但智能手表上的重启操作与平板电脑上的不同。因此,如果我们重启智能手表和 Trouvez Tablet,我们使用了共同的操作(重启),但每个模型都以自己的方式执行该操作,基本上,从更抽象的层面来看,我们有两个小工具在执行重启操作时表现出多态行为(基于它们的类型)。

什么是 Python?

Python 是一种动态类型、通用、高级编程语言。它由 Guido van Rossum 设计和开发,并于 1991 年公开发布。如今,它非常流行,主要用于 Web 开发,以及像 Django、 Flask、 Bottlepy 和 Pyramid 这样广泛的 Web 框架。该语言的名称来源于 Monty Python's Flying Circus,Guido 是其忠实粉丝。

我应该使用哪个版本,2.x 还是 3.x?

Python 的 2.7.x 版本将正式支持到 2020 年。该语言的核心开发团队确认不会有 2.8 版本。他们只会为 2.x 分支提供安全更新和错误修复。3.x 分支于 2000 年发布,早期存在问题,但现在非常好。迁移到新版本很困难,因为大多数 Linux 发行版仍然附带 2.x 版本。这主要是由于向后兼容性;有大量应用程序使用 2.x 分支编写,人们不希望破坏现有应用程序。3.x 分支可以轻松地与 2.x 并排安装,并且可以毫无问题地使用。

有关 Python 2.x 和 3.x 分支差异、优缺点更详细的解释,请阅读这两篇文章

Python 中的类

如上所述,类是对象的类型定义。Python 中类的声明使用 class 关键字。Python 中有一个编码约定,通常一个 .py 文件只包含一个类定义。可以有例外,但这遵循良好的实践。下面是一个我之前提到过的 Gadget 类的例子:

class Gadget:
    weight = 100
    operating_system = None
    battery_capacity = 2000
    screen_size = 1
 
my_iphone = Gadget()

该 Gadget 类有 4 个属性(weightbattery_capacityoperating_systemscreen_size)。我们可以使用类名和括号创建类的实例 – Gadget()。如果我们查看类的默认值,考虑到 iPhone 的技术参数,这些值似乎不正确。我们需要一个方法或函数来让我们为类的给定实例指定值。有助于创建类新实例的方法称为构造函数。下面是 Python 中构造函数(__init__)的实现。 __init__ 方法在创建新实例后立即被调用。构造函数的第一个参数称为 self。这是另一个代码约定。第一个参数代表新创建的对象。可以看到我们在构造函数中设置了 self 的属性。

class Gadget:
    weight = 100
    operating_system = None
    battery_capacity = 2000
    screen_size = 1
 
    def __init__(self, weight, operating_system, battery_capacity, screen_size):
        self.weight = weight
        self.operating_system = operating_system
        self.battery_capacity = battery_capacity
        self.screen_size = screen_size
 
 
my_iphone = Gadget(weight = 128, operating_system="iOS", battery_capacity=2800, screen_size=4)

如果我们想查看新对象具有什么值,我们可以打印这些值。

my_iphone = Gadget(weight = 128, operating_system="iOS", battery_capacity=2800, screen_size=4)
 
print(my_iphone.weight)
print(my_iphone.operating_system)
print(my_iphone.battery_capacity)
print(my_iphone.screen_size)

这种方法有一个问题,我们违反了 封装 规则。我们可以直接访问 my_iphone 对象的内部状态,我们可以简单地为 screen_size 或 operating_system 属性分配新值。模型的当前实现允许这样做。我们应该通过使用属性并隐藏当前类成员的公共访问来更改这些。

class Gadget:
    """A class used for modelling Gadgets in a web shop."""
    __weight = 100
    __operating_system = None
    __battery_capacity = 2000
    __screen_size = 1
 
    def __init__(self, weight, operating_system, battery_capacity, screen_size):
        self.__weight = weight
        self.__operating_system = operating_system
        self.__battery_capacity = battery_capacity
        self.__screen_size = screen_size
 
    def get_weight(self):
        return self.__weight
 
    def set_weight(self, weight):
        self.__weight = weight
 
    weight = property(get_weight, set_weight)
 
    @property
    def operating_system(self):
        return self.__operating_system
 
    @operating_system.setter
    def operating_system(selg, new_os):
        self.__operating_system = new_os

我们可以通过使用 __[attribute_name] 语法来隐藏属性(使其成为私有)(有关这些约定的更详细信息,请阅读 Python PEP 8 风格指南),并且我们可以创建 setter 和 getter 方法来访问私有属性。使用 getter 和 setter 方法是可以的,但它提供了类似 Java 的编码体验,其中可以使用 get 和 set 方法 设置类变量。一种更对开发者友好的方法是使用属性。我创建了 2 个属性(用于 weight 和 operating_system),每种都以不同的方式实现。

在实现 weight 的属性时,我使用了 weight = property(get_weight, set_weight) 方法来创建 weight 属性。这种语法可以轻松应用于 Python 类,其中首先实现了类似 Java 的 get/set 方法方法,然后使用 property(get…, set…) 方法,我们可以用属性扩展类。

在实现 operating_system 的属性时,我使用了另一种方法,一种称为注解/装饰器的方法。在这里,我首先定义了 get 方法,但省略了 get 关键字(请注意,用 @property 装饰的方法 operating_system 只有一个参数,即 self);然后我创建了 setter,它具有相同的(operating_system)方法名,但有两个参数,即 self 和需要设置的新值(称为 new_os)。

>>> from Gadget import Gadget

>>> my_iphone = Gadget(240,'iOS',1980,4)

>>> my_iphone.weight

240

>>> my_iphone.weight = 255

>>> my_iphone.weight

255

>>>

>>>

>>> my_iphone.operating_system

'iOS'

>>> my_iphone.operating_system = 'iOS 8.1'

>>> my_iphone.operating_system

'iOS 8.1'

>>>

使用属性非常简单,这里有一些例子。基本上,属性的行为与公共成员相同,但通过 getter 和 setter,我们可以选择验证新设置的值(在此情况下我没有进行任何验证,但可以轻松完成)。

Python 中的 OOP - 第二部分即将推出。

© . All rights reserved.