Python 中的 OOP - 第一部分。






4.69/5 (15投票s)
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 个属性(weight、battery_capacity、operating_system 和screen_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 - 第二部分即将推出。