文章目录
一、理解面向对象编程
举例:我们以对象Car为例子进行说明,对象Car不仅拥有多种属性,如fuel_level(油位), speed(速度),steering_whell(方向盘)等等属性。还拥有一些方法,如accel_erate()提供速度,takeleft()提供向左转向。在python中一切皆对象,每个类的实例或变量都有其自身的内存地址。
1.对象
- 他们表示所开发的应用程序内的实体
- 实体之间可以通过交互来解决现实世界的问题。
- Person(人)是实体,Car(汽车)也是实体,Person可以驾驶着Car,从一个地方到另一个地方。
2.类
可以帮助开发人员表示现实世界中的实体
- 类可以定义对象的属性和行为,属性是数据成员,行为由成员函数表示。
- 类包含了构造函数,这些函数的作用是为了对象提供初始状态。
- 类就像模板一样,非常易于重复谁用。
例如,类Person可以带有属性name和age,同时提供函数eat(),定义了吃饭的行为。
3.方法
- 它们表示对象的行为。
- 方法可以对属性进行处理,从而实现所需的功能。
例:创建类和对象的例子:
# -*- coding: utf-8 -*-
# @Time : 2020/4/30 下午 04:20
# @Author : lh
# @Email : xx@lh.com
# @File : test.py
# @Software: PyCharm
class Person(object):
# 构造函数 constructor
def __init__(self, name, age):
self.name = name
self.age = age
def get_person(self):
return "他的名字是{0},年龄为{1}".format(self.name, self.age)
p = Person('John', 32) # p 是Person的实例化对象
print("对象类型:{0}, 内存地址是{1}", format(type(p), id(p))) # 对象类型:{0}, 内存地址是{1} <class '__main__.Person'> 2075809833792
面向对象编程的主要概念:
1.封装
- 对象的行为对于外部世界来说是不可见的,或者说对象的状态信息是私密的。
- 客户端不能直接操作来改变对象的内部状态。相反,客户端需要通过发送消息来请求对象改变其内部状态,对象可以根据请求的类型,通过特定的成员函数(get or set)改变它们的内部状态,以做出相应的响应。
- 在python中,封装(数据和方法的隐藏)的概念不是隐式的,因为它没有提供封装所需的关键字,比如java中的public private protected。但是python可以在变量或函数名前面加上前缀__,就可以将其可访问性变为私有。
2.多肽
- 多肽有两种类型:
- 对象根据输入参数提供方法的不同实现。
- 不同类型的对象可以使用相同的接口。
- 对于python来说,多肽是python中的内置功能,比如:操作符“+”可以应用于两个整数进行加法运算,也可以应用于字符串的拼接。
示例:字符串、元组或者列表都可以通过整数索引进行访问。
这为我们展示了python内置类型的多肽。
a = 'Bob
b = (1, 2, 3)
c = [9, 8, 7]
print(a, b, c)
3.继承
- 一个类可以继承父类的(大部分)功能。
- 一个重用基类中定义的功能并允许对原始软件的实现进行独立拓展的选项。
- 可以利用不同类的对象之间的关系建立层次结构。与java不同得是,python支持多重继承(继承多个基类)。
class A:
def a1(self):
print("a1")
class B(A):
def b(selfs):
print('b')
b = B()
b.a1()
4.抽象
- 它提供了一个简单的客户端接口,客户端可以通过该接口与类的对象进行交互,并可以调用该接口中定义的各个方法。
- 它将内部类的复杂性抽象为一个接口,这样客户端就不需要知道内部实现了。
class Adder:
def __init__(self):
self.sum = 0
def add(self, value):
self.sum += value
acc = Adder()
for i in range(99):
acc.add(i)
print(acc.sum)
二、面向对象的设计原则
1.开放/封闭原则
- 开闭原则,类或对象及其方法对于拓展来说,应该是开放的,对于修改来说,应该是封闭的。
- 这意味着你在开发软件应用的时候,一定确保以通用的方式来编写类或模块。以便需要将拓展类或对象行为的时候不必修改类本身。相反类的简单拓展将有助于建立新的行为。
- 开闭原则的体现:为了实现所需行为,用户必须通过扩展抽象基类来创建类的实现。而不是通过修改抽象类。
- 优点:
- 1.现有的类不会被修改,所以退化的可能性较小。
- 2.有助于以前代码的向后兼容性。
2.控制反转原则
- 控制反转原则是指,高级的模块不应该依赖于低层级的模块,应该依赖于抽象。细节应该依赖于抽象,而不是抽象依赖于细节。
该原则建议任何两个模块都不应以紧密方式相互依赖,事实上,基本模块和从属模块应当在他们之间提供一个抽象层来耦合。这个原则还建议类的细节应该描绘抽象。在某些情况下,这种观念会反转。也就是实现细节本身决定了抽象,这种情况应该避免的。 - 优点:
- 1.消弱了模块间的紧耦合,因此消除了系统中的复杂性/刚性。
- 2.由于在依赖模块之间有一个明确的抽象层(由钩子或参数提供),因此便于通过更好的方式处理 模块之间的依赖关系。
3.接口隔离原则
- 接口隔离原则规定,客户端之间不应该依赖于他们不需要使用的接口。
- 接口隔离原则的意思就是,软件开发人员应该仔细地处理接口。例如,它提醒开发人员/架构开发师开发的方法要与特定功能紧密相关。如果存在与接口无关的方法,那么依赖于该接口的类就必须实现它,实际上这是毫无必要的。
- 例:一个Pizza的接口不应该提供名为add_chicken()的方法。基于Pizza接口的Veg Pizza类不应该强制实现该方法。
- 优点:
- 1.它强制开发人员编写‘瘦身型’接口,并使用方法与接口紧密相关
- 2.防止向接口中随意添加方法。
4.单一职责原则
- 单一职责的含义:类的职责单一,引起类变化的原因单一。
- 这个原则就是说,当我们开发类时,它应该为特定的功能服务。如果一个类实现了两个功能,那么最好将它们分开。也就是说,功能才是改变的理由。例如,一个类可以因为所需行为的变化进行修改。但是一个类由于两个因素(基本上是两个功能的改变)而改变,那么该类就应该进行相应的分离。
- 优点:
- 1.每当一个功能发生变化时,除了特定的类需要改变外,其它类无需变动。
- 2.此外,如果一个类有多种功能,那么依赖它的类必定会由于多种原因而经历多次修改,这是应该避免的。
5.替换原则
- 替换原则规定,派生类必须能够完全替代基类。
- 这个原则狠简单。当应用程序开发人员编写派生类时,该原则的含义就是他们应该扩展基类。此外,它还建议派生类应该尽可能对基类封闭,以至于派生类本身可以替换基类,而无需修改任何代码。