面向对象编程基础

一、面向对象概念

1.1 什么是面向过程

​ 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

​ 生活中的的例子举例。

1.2 什么是面向对象

​ 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

  1. 面向对象是一种思维方法
  2. 面向对象是一种编程方法
  3. 面向对象并不只针对某一种编程语言

1.3 面向对象和面向过程的区别和联系

面向过程,做什么

面向过程过程侧重整个问题的解决步骤,着眼局部或者具体,核心:过程的实现

【面向过程】:

为了把大象装进冰箱,需要3个过程。

  1. 把冰箱门打开(得到打开门的冰箱)
  2. 把大象装进去(打开门后,得到里面装着大象的冰箱)
  3. 把冰箱门关上(打开门、装好大象后,获得关好门的冰箱)

    每个过程有一个阶段性的目标,依次完成这些过程,就能把大象装进冰箱。

面向对象,谁来做

面向对象侧重具体的功能,让某个对象具有这样的功能。更加侧重于整体。核心:对象

【面向对象】:

为了把大象装进冰箱,需要做三个动作(或者叫行为)。

每个动作有一个执行者,它就是对象。

  1. 冰箱,你给我把门打开
  2. 大象,你给我钻到冰箱里去
  3. 冰箱,你给我把门关上

    依次做这些动作,就能把大象装进冰箱。
各自的优缺点

面向过程的优点:
流程化使得编程任务明确,在开发之前基本考虑了实现方式和最终结果;
效率高,面向过程强调代码的短小精悍,善于结合数据结构来开发高效率的程序。。
流程明确,具体步骤清楚,便于节点分析。 缺点是:需要深入的思考,耗费精力,代码重用性低,扩展能力差,维护起来难度比较高,
对复杂业务来说,面向过程的模块难度较高,耦合度也比较高。 面向对象的优点:结构清晰,程序便于模块化,结构化,抽象化,更加符合人类的思维方式;
封装性,将事务高度抽象,从而便于流程中的行为分析,也便于操作和自省;
容易扩展,代码重用率高,可继承,可覆盖;
实现简单,可有效地减少程序的维护工作量,软件开发效率高。 缺点是:效率低,面向对象在面向过程的基础上高度抽象,从而和代码底层的直接交互非常少机会,
从而不适合底层开发和游戏甚至多媒体开发;
复杂性,对于事务开发而言,事务本身是面向过程的,过度的封装导致事务本身的复杂性提高。

编程语言对面向对象的实现主流的有两种方式:基于类的面向对象和基于原型的面向对象。

不管以什么方式实现,都具有面向对象的三大特征:

  • 封装

    也就是把客观事物封装成抽象的类或具体的对象,并且类或对象可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

  • 继承

    可以让某个类型的对象获得另一个类型的对象的属性的方法

  • 多态

    不同实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。

1.4编程语言中面向对象的实现方式

1.4.1基于类的面向对象

典型的语言:Java、C#、 pthon 、c++等

对象(object)依靠 类(class)来产生

1.4.2基于原型的面向对象

典型的语言:JavaScript

对象(object)则是依靠 构造器(constructor)利用 原型(prototype)构造出来的

二、python中的类

python 是基于类的面向的对象语言, 所以学习 python 面向对象, 必须要先学习类

2.1类和实例的概念

通过前面的学习我们已经知道, 面向对象编程(Object Oriented Programming,简称OOP),是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了 数据和操作数据的函数(方法)

而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。


2.1.1 类的理解

在 python 中所有类型的数据都可以看成对象, 包括我们我们以前学习的所有的内置类型int, float等.

像这些 int, float, list这些数据类型, 就是我们面向对象中的类

我们可以根据需要自定义很多类型出来, 这些自定义的类型也是我们面向对象中的类


2.1.2对象的理解

我们天天说对象, 到底该怎么去理解对象?

a = 3 变量 a 赋值为整数 3, 这里的 3 就是一个int类型的对象.

nums = [2, 4, 1] 这里的 [2, 4, 1] 就是list类型的列表对象.

可以这么说, 在 python 中任何类型的数据数据都是对象.(和其他语言 c++, java 等不太一样, 他们有一些不是对象的基本数据类型)

对象其实就是对数据和操作数据的方法进行的封装


2.1.3类与对象的关系

类与对象的关系, 就是我们每个人同人类的关系一样.

人类是对每个具体的人的共同的特点的抽象. 比如都有手脚, 耳朵, 还都可以吃饭, 娱乐, 男人还可以去大保健. 人类就是编程语言中的类型.

而每个人是人类的一个个的具体的实现. 每个人都是编程语言中的一个对象


类是对对象的抽象描述, 而对象是类的具体实现. 他们是抽象与具体的关系.


例如:

汽车制造图纸和一个个的汽车.

图纸就是类, 汽车就是对象


2.1.4先有对象还是先有类

看情况:

  1. 在做面向对象分析的时候, 一般是先有对象, 然后把对象的共性抽象出来, 然后就形成了类.
  2. 编写代码的时候, 一般是先完成类的编写, 然后在需要的时候创建对象就可以了.

2.2 定义类

我们需要关键字class来定义类

class 类名:
# 类中定义的内容

比如我们定义一个表示学生的Student类:

class Student:
pass

说明:

  1. class 后面紧跟类名. 类名的命名使用驼峰命名法.
  2. 类名的后面跟一个冒号
  3. 然后是带有正确缩进的类的主体.(上面的例子中使用 pass, 表示空的类主体)

2.3创建对象

定义类的目的就是使用类来创建对象.

在 python 中使用类创建对象与其他语言差别较大, 其他语言需要使用关键字new, python 精简了创建方式, 我们不需要new.

2.3.1 python 就是以函数形式调用来创建对象的!


python 创建对象直接使用类名()就可以了.

class Student:
pass s1 = Student() # 使用类创建对象
print(s1)

创建对象的过程是不是和方法调用一样一样的?!

2.4类定义的深入研究

类必须先定义再使用

类的定义与函数定义是一样的, 都要遵循先定义再使用

s2 = Student()    # 此处无法使用类来创建对象

class Student:
pass

可以在if语句中甚至函数中定义类

if True:
class Student:
pass s1 = Student()
print(s1)

使用类的时候, 一定要保证类被已经被定义了.


类的主体

类主体中都可以定义什么?

在 python 中类可以定义:


1. 字段(field, 在国内很多人叫属性)

在 python 中字段分 2 种:

  1. 实例变量(Instance Variables):

    他存储的值是属于每一个对象的, 或者对不同的对象来说他们是独立. 就像人的私有财产
  2. 类变量(Class Variables):

    他存储的值是属于类本身的, 而不是属于某一个具体的对象, 或者说他是被所有的对象所共有的. 就像公共财产

2. 方法

方法就是我们以前学习的函数, 只是同类扯上关系了而已!

在 python 中的方法分 3 种:

  1. 实例方法.

    和实例变量一样, 他是属于对象的.

    实例方法相比普通的函数有一个比较特殊的地方:第一个形参总是会自动传入这个实例(对象)
  2. 类方法

    和类变量一样, 是属于类的.

    类方法与实例方法的区别在于第一个参数: 类方法的第一个参数总是这个类本身.
  3. 静态方法

    静态方法和实例没有任何关系. 它仅仅是定义在类中而已, 这个时候类就相当于这个方法的命名空间.

2.4.1类中定义字段

2.4.1.1类变量

类变量表示所有的对象所共有的一种数据.换句话说, 所有的对象都可以直接访问到, 并且他们访问到的是同一个变量(肯定是相同的值!)

把变量直接声明在类的内部的变量.

访问类变量直接通过类名.变量名来访问.

class Student:
# 直接在类中定义变量,
# 这样的变量就是类变量(类属性, 类似 java 中的静态属性)
country = "china" print(Student.country)
# 修改类变量的值
Student.country = "usa"
print(Student.country)


当然你也可以在任何的地方通过类名.属性=值的方式动态给类添加类属性.

class Student:
# 直接在类中定义变量,
# 这样的变量就是类变量(类属性, 类似 java 中的静态属性)
country = "china" Student.count = 1 # 动态添加类属性
print(Student.count)

但是, 建议在类中直接定义类属性, 只有在需要的时候才使用动态的方式添加类属性.


2.4.1.2 实例变量

实例变量表示每个对象都自己所独有.

所以, 实例变量与每个具体的对象相关.

添加实例变量:

一般是在一个叫做__init__()的方法里面来添加. (关于方法下节再细讲, 现在你只需要知道他是一个函数就可以了)

__init__(), 注意他是左右分别有 2 个_. 这个方法不需要我们手动去调用, 当你使用类创建对象的时候, 会自动调用这个方法.

这个方法的第 1 个参数永远是创建的那个对象(所有的实例方法都是这样的), 我们可以通过这个参数来向对象中添加属性, 这样的属性就是实例属性.

作为国际惯例, 第 1 个参数的一般都命名为self, 当然你也可以给他起个别的名字, 但是何必呢!


class Student:
def __init__(self):
self.name = "李四"
self.age = 20 s = Student()
print(s.name)
print(s.age)


上面这种写法, 会导致使用这个类创建的对象的nameage这个两个实例变量的值都会初始化为同样的值, 这其实并不好.

我们想每个变量初始化的值都不一样, 可以在创建的对象的是把具体的值沟通过实参传递过去, 则实参会自动传到__init__()方法的第 2 个开始的参数中.

class Student:
def __init__(self, name, age):
self.name = name
self.age = age zs = Student("张三", 20)
print(zs.name + " " + str(zs.age))
ls = Student("李四", 30)
print(ls.name + " " + str(ls.age))

你会发现每个对象的值都不一样的!


2.4.1.3 可以通过对象直接访问类变量

python 允许通过对象直接访问到类变量. (有些语言是不允许的, 比如 c#, JavaScript 就不允许, 但是 java 允许)

class Student:
country = "china" def __init__(self, name, age):
self.name = name
self.age = age zs = Student("张三", 20)
print(zs.name + " " + str(zs.age))
ls = Student("李四", 30)
print(ls.name + " " + str(ls.age)) print(zs.country) # 通过对象直接访问类变量
print(ls.country)


2.4.2 类中定义方法

2.4.2.1. 定义实例方法

实例方法和普通方法的区别:

  1. 实例方法必须定义在类中
  2. 实例方法的第一个参数永远是那个具体的对象, 而且不需要调用者手动传入, python 会自动传入那个对象. 而且这个形参一般命名为self
  3. 实例方法调用方式:对象.实例方法(实参)

class Student:
def __init__(self, name):
self.name = name # 定义一个实例方法:一个参数表示具体的对象, python 会默认传入
def speak(self):
print("我的名字是:" + self.name) # 在实例方法中访问实例变量 s = Student("志玲")
s.speak()


self的理解

学过其他语言的人都知道, python 的 self 其实就是在其他语言的this.

那么self到底指代哪个对象?

通过哪个对象调用的这个实例方法, 那么这个实例方法中的self就指代谁

而且 python 的self一朝绑定, 终身不变. (不像 javascript 中的那个 this 小婊砸随着调用方式的不同而而更改绑定对象, 让你眼花缭乱到怀疑人生)


class Student:
def __init__(self, name):
self.name = name # 定义一个实例方法:一个参数表示具体的对象, python 会默认传入
def speak(self):
print("我的名字是:" + self.name) # 在实例方法中访问实例变量 s = Student("志玲")
# s.speak 的 this 永远指定的是 s 对象
foo = s.speak # 重新定义一个变量, 指向了对象 s 的 speak 方法.
foo() # 则 self 仍然绑定的是 s 对象


class Student:
def __init__(self, name):
self.name = name def speak(self):
print("我的名字是:" + self.name) # 在实例方法中访问实例变量 s1 = Student("志玲")
s2 = Student("凤姐") s2.speak = s1.speak s2.speak()

说明:

s1.speak表示的那个方法赋值给s2.speak, 虽然你调用的时候使用的是s2.speak(), 但是他指向的那个方法的self已经永远的绑定到了s1


2.4.2.2. 定义类方法

类方法和实例方法的区别:

  1. 一个方法想成为类方法, 需要在方法的上面要添加一个内置装饰器:@classmethod
  2. 实例方法的第一个参数是具体的对象, 而类方法的第一个参数是类对象.(python 中一切皆对象, 那么类本身也是个对象, 我们一般称之为类对象). 类对象也是 python 自动传递. (类对象一般起名为 cls)
  3. 调用实例方法使用对象.实例方法(实参), 而调用类方法使用类名.类方法(实参)
  4. 类方法中可以访问类变量, 但是不能访问实例变量, 因为没有self啊.

class Student:
country = "china" @classmethod
def say(cls):
print("我们的国家是:" + cls.country) Student.say()


什么时候使用类方法

如果一个方法不需要操作实例变量, 则这个方法建议定义成类方法!


注意:

有一点注意, 类方法也可以通过实例对象来调用, 但是不管怎么调用, 类方法的第一个参数总是类对象!

class Student:
country = "china" @classmethod
def say(cls):
print("我们的国家是:" + cls.country) Student.say()
s = Student()
s.say()


2.3.2.3. 定义静态方法

静态方法其实是一种普通的函数, 他仅仅是处于类的命名空间中.(把当前类作为了他的命名空间, 其他情况与普通函数没有任何区别).

  1. 定义静态方法只需要在函数的上面添加一个装饰器:@staticmethod
  2. 调动静态方法: 类名.静态方法(实参). 只需要把类名作为他的前缀来执行, 与普通函数相比, 没有其他任何多余的操作!

class Student:
@staticmethod # 定义静态方法
def create_student():
print("我是个静态方法") Student.create_student()


静态方法的应用场景

因为 python 的类中只有一个__init__()方法, 意味着创建对象的方式只能有一种.

我们可以使用静态方法给外界提供其他的创建对象的方式.


import time
class Date:
"""
创建一个表示日期的类
"""
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day @staticmethod
def now():
"""
创建表示当前日期的对象
:return:
"""
t = time.localtime()
return Date(t.tm_year, t.tm_mon, t.tm_mday) @staticmethod
def tomorrow():
"""
创建表示明日日期的对象
:return:
"""
t = time.localtime(time.time() + 60 * 60 * 24)
return Date(t.tm_year, t.tm_mon, t.tm_mday) now = Date.now()
print("现在是: %d年%d月%d日" % (now.year, now.month, now.day))
now = Date.tomorrow()
print("明天是: %d年%d月%d日" % (now.year, now.month, now.day))

2.4.3 python中的__init()__方法

在任何一个 python 类中, 都存在一个__init__()的方法, 而且只能存在一个.

我们不管用什么办法创建对象, 都会自动的去执行__init__()方法

默认情况下的__init()__

默认情况, __init()__什么都不做.

__init__()初始化实例变量

__init()__方法的主要作用就是添加并初始化实例变量. 初始化的实例变量的值在创建对象的时候通过实参传递过来.

__init__()的第一个形参总是新创建的那个实例对象.

Python第七章-面向对象的更多相关文章

  1. Python第七章-面向对象高级

    面向对象高级 一. 特性 特性是指的property. property这个词的翻译一直都有问题, 很多人把它翻译为属性, 其实是不恰当和不准确的. 在这里翻译成特性是为了和属性区别开来. 属性是指的 ...

  2. 简学Python第七章__class面向对象高级用法与反射

    Python第七章__class面向对象高级用法与反射 欢迎加入Linux_Python学习群  群号:478616847 目录: Python中关于oop的常用术语 类的特殊方法 元类 反射 一.P ...

  3. <automate the boring stuff with python>---第七章 正则实例&正则贪心&匹配电话号码和邮箱

    第七章先通过字符串查找电话号码,比较了是否使用正则表达式程序的差异,明显正则写法更为简洁.易扩展.模式:3 个数字,一个短横线,3个数字,一个短横线,再是4 个数字.例如:415-555-4242 i ...

  4. Python第六章 面向对象

    第六章 面向对象 1.面向对象初了解 ​ 面向对象的优点: ​ 1.对相似功能的函数,同一个业务下的函数进行归类,分类 ​ 2.类是一个公共的模板,对象就是从具体的模板中实例化出来的,得到对象就得到一 ...

  5. 流畅的python第七章函数装饰器和闭包学习记录

    本章讨论的话题 python如何计算装饰器句法 python如何判断变量是不是局部的(通过函数内部是否给变量赋值过来判断是否是局部变量) 闭包存在的原因和工作原理(闭包是一种函数,它会保留定义函数时存 ...

  6. Python第七章(北理国家精品课 嵩天等)

    7.1文件的使用 1.1文本类型 文本文件:由单一特定编码组成的文件,如.txt 二进制文件:如.png,.avi 1.2文件的打开和关闭 打开-操作-关闭 <变量名> = open(&l ...

  7. python第七章:常用模块--小白博客

    yagmail模块 python标准库中发送电子邮件的模块比较复杂,因此,有许多开原的库提供了更加易用的接口来发送电子邮件,其中yagmail是一个使用比较广泛的开原项目,yagmail底层依然使用了 ...

  8. java 第七章 面向对象高级特性

    一.类的继承 (一)继承的含义 1.在Java中定义一个类时,让该类通过关键字extends继承一个已有的类,这就是类的继承(泛化). 2.被继承的类称为父类(超类,基类),新的类称为子类(派生类). ...

  9. 简学Python第六章__class面向对象编程与异常处理

    Python第六章__class面向对象编程与异常处理 欢迎加入Linux_Python学习群  群号:478616847 目录: 面向对象的程序设计 类和对象 封装 继承与派生 多态与多态性 特性p ...

随机推荐

  1. redis BLPOP

    一.需求 redis中保存了需要download的image url,存储格式为列表. 我需要从列表中获取数据,将图片下载保存到本地. 列表中的数据是一直增加的. 二.实现 使用redis BLPOP ...

  2. GDB调试系列之了解GDB

    想要熟练利用GDB进行程序调试,首先要了解什么是GDB. 1. 什么是GDB GDB (the GNU Project Debugger) 是一个可以运行在大多数常见的UNIX架构.Windows.M ...

  3. 分割文件和数据(linux)

    在某些情况下,必须把文件分割成多个更小的片段.如今我们分割文件的目的比如:提高可读性.生成日志.通过Email发送文件等等. 假设我们有一个erro.log的测试文件,其大小为14M.你可以将该文件分 ...

  4. 7-29 jmu-python-不同进制数 (10 分)

    输入一个十进制整数,输出其对应的八进制数和十六进制数.要求采用print函数的格式控制进行输出,八进制数要加前缀0o,十六进制数要加前缀0x. 输入格式: 输入一个十进制整数,例如:10 输出格式: ...

  5. Asp.Net Core Endpoint 终结点路由之中间件应用

    一.概述 这篇文章主要分享Endpoint 终结点路由的中间件的应用场景及实践案例,不讲述其工作原理,如果需要了解工作原理的同学, 可以点击查看以下两篇解读文章: Asp.Net Core EndPo ...

  6. 微信小程序学习 动手撸一个校园网小程序

    动手撸一个校园网微信小程序 高考完毕,想必广大学子和家长们都在忙着查询各所高校的信息,刚好上手微信小程序,当练手也当为自己的学校做点宣传,便当即撸了一个校园网微信小程序. 效果预览 源码地址:Gith ...

  7. js的Set和Map集合

    目录 1.js的Set介绍 1-1.Set基础用法 1-2.Set对象的操作方法 1-3.Set对象的遍历方法 2.js的Set扩展WeakSet篇 3.js的Map介绍 3-1.Map基础用法 3- ...

  8. 脚本写一行echo也能写出bug ? glob了解一下

    背景 最近处理一个 bug 很有意思,有客户反馈某个配置文件解析失败了,出错的那行的内容就只有一个字母 a. 最开始以为是谁改动了处理的脚本,但要到了问题代码中的脚本,比较发现跟库上是一样的. 又经过 ...

  9. 程序员过关斩将-- 喷一喷坑爹的面向UI编程

    摒弃面向UI编程 为何喷起此次话题,因为前不久和我们首席架构师沟通,谈起程序设计问题,一不小心把UI扯进来,更把那些按照UI来编程的后台工程师也扯了进来.今天特意百度了一下(其实程序员应该去googl ...

  10. PDA程序开发的运行配置

    前言:因为这个项目是公司一直在做的项目,所以只是简单说一下我从下载项目到成功运行的配置 开发工具:APICloud.雷神模拟器.Visusl studio vs配置: 1.svn下载后台代码后,修改w ...