什么是OOP(面向对象编程)?
面向对象编程是一种编程范例,它在编程阶段创建“对象”,试图根据需要解决的问题对实体进行建模。
“对象”包含数据作为字段的形式(也称为属性)并定义了操作(称为方法)。“对象”具有类型定义,这些在编程术语中称为类。“对象”是类的实例。
当我们讨论OOP(也称为OOP的三大支柱)时,有三个关键的事情需要讨论:
- 封装 - 意味着将数据和与类中数据交互的方法锁定在一个单元中。这很有用,因为模型的内部结构只能通过它公开的方法来改变,其他实体(对象)不能修改另一个的内部状态。
- 继承 - 通常当我们构建关于现实世界问题的模型时,我们最终会遇到大对象层次结构。这些模型(类)之间具有相互关系。模型层次结构中的 “是一个”关系是使用OOP中的继承实现的,这意味着一个模型(或对象)中存在的特征也将存在于派生模型中。
- 示例: 让我们假设您要构建自己的网上商店,并且想要销售小工具。小工具具有电池容量,重量,内存量,操作系统等属性。如果你想在你的网上商店出售平板电脑,你可以说 平板电脑是一个小工具,在代码中实现这些时,您可以使用继承将Gadget类的所有属性和功能传递给Tablet类。
- 多态性 - 被称为对象基于其具有的子类型以不同方式行为的可能性。多态性与遗传有关。
- 示例: 假设您希望在网上商店销售智能手表。一个 智能手表是一个小工具。可以重新启动所有小工具,这可以是小工具的操作(或方法)。由于两者(平板电脑和智能手表)都继承自Gadget(它们之间存在关系),因此它们也继承了重启操作,但是对于平板电脑,智能手表上的重启操作是不同的。因此,如果我们重新启动智能手表和平板电脑,我们使用了常用操作(重启),但每个模型都以自己的方式执行操作,基本上,从更抽象的层面查看它我们有2个小工具执行重启操作时的多态行为(基于其类型)。
什么是Python?
Python 是一种动态类型,通用的高级编程语言。它由Guido van Rossum 设计和开发, 并于1991年向公众发布。如今它非常受欢迎,主要用于web开发以及广泛的web框架,如 django , flask , bottlepy 和 pyramid 。该语言的名称源自 Monty Python的飞行马戏团 ,Guido是其中的忠实粉丝。
我应该使用哪个版本,2.x或3.x?
2.7.x版本的Python将在2020年之前得到官方支持。该语言的核心开发团队确认不会有2.8版本的语言。他们只会为2.x分支发布安全更新和错误修复。3.x分支于2000年发布,它在一开始就有问题,但现在非常好。过渡到新版本很难,因为大多数Linux发行版仍然附带版本2.x. 这背后的主要原因是向后兼容; 有许多使用分支2.x编写的应用程序,人们不想破坏现有的应用程序。分支3.x可以在2.x之外轻松安装,并且可以毫无问题地使用。
Python中的类
如上所述,类是对象的类型定义。Python中的类声明是使用class 关键字完成的 。python中有一个编码约定,通常 .py 文件只包含一个类定义。可能有例外,但这是一个很好的做法。这是我之前谈到的Gadget类的一个例子:
class Gadget: weight = 100 operating_system = None battery_capacity = 2000 screen_size = 1 my_iphone = Gadget()
的 小工具 类有4个属性(重量, 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 对象,我们可以简单的分配新的值给 小号creen_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] 语法声明它们,我们可以隐藏属性(使它们成为私有) (有关这些约定的更多详细信息,请阅读 PEP 8样式指南),我们可以创建 用于访问私有的setter和getter方法属性。使用 getter和setter 方法很好,但是它提供了类似Java的编码体验,其中可以使用get和set方法设置类变量 。更加开发人员友好的方法是使用属性。我创建了2个属性(对于weight 和 operating_system),每个属性 都以不同的方式实现。
在实现权重属性时 ,我使用了 weight = property(get_weight,set_weight) 方法来创建 权重 属性。这个语法可以很容易地应用于python类,其中首先实现类似Java的get / set方法,并使用 属性(get ...,set ...) 方法,我们可以使用属性扩展类。
在为operating_system实现属性时, 我使用了另一种方法,即所谓的注释/装饰器。这里,首先我定义了get方法,但是我省略了get关键字(请注意用@property修饰的方法operating_system只有一个参数self); 之后我创建了setter,它具有相同的方法名称(operating_system)但有2个参数,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,我们可以选择验证新设置的值(在这种情况下我没有进行任何验证,但可以毫无问题地完成)。