一、 什么是面向对象的程序设计及为什么要有它

1、面向过程

  面向过程的程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种机械式的思维方式。

  优点是复杂度的问题流程化,进而简单化(一个复杂的问题,分成一个个小的步骤去实现,实现小的步骤将会非常简单)

  缺点是一套流水线或者流程就是用来解决一个问题,牵一发而动全身。

  应用场景:一旦完成基本很少改变的场景。

2、面向对象 

  面向对象的程序设计:核心是对象二字,对象是特征与技能的结合体,基于面向对象设计程序就好比在创造一个世界,你就是这个世界的主宰,存在的皆为对象,不存在的也可以创造出来,与面向过程机械式的思维方式形成鲜明对比,面向对象更加注重对现实世界的模拟,是一种“主宰式”的思维方式。

  优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。

  缺点:

  1. 编程的复杂度远高于面向过程,一些扩展性要求低的场景使用面向对象会徒增编程难度,比如管理linux系统的shell脚本就不适合用面向对象去设计,面向过程反而更加适合。

  2. 无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法准确地预测最终结果。于是我们经常看到对战类游戏,新增一个游戏人物,在对战的过程中极容易出现阴霸的技能,一刀砍死3个人,这种情况是无法准确预知的,只有对象之间交互才能准确地知道最终的结果。

  应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方

面向对象的程序设计并不是全部。对于一个软件质量来说,面向对象的程序设计只是用来解决扩展性。

二 、类与对象

  类即类别、种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体

那么问题来了,先有的一个个具体存在的对象(比如一个具体存在的人),还是先有的人类这个概念,这个问题需要分两种情况去看

在现实世界中:先有对象,再有类

  世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念

也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在

在程序中:务必保证先定义类,后产生对象

  这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类

不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象

按照上述步骤,我们来定义一个类:

#在程序中,务必保证:先定义类,后调用类来产生对象
PS:
1. 在程序中特征用变量标识,技能用函数标识
2. 因而类中最常见的无非是:变量和函数的定义 #程序中的类
class Heros:
birthplace='王者荣耀'
def attcck(self): #普通的攻击技能
pass #注意:
1.类中可以有任意python代码,这些代码在类定义阶段便会执行
2.因而会产生新的名称空间,用来存放类的变量名与函数名,可以通过Heros.__dict__查看
3.对于经典类来说我们可以通过该字典操作类名称空间的名字(新式类有限制),但python为我们提供专门的.语法
4.点是访问属性的语法,类中定义的名字,都是类的属性 #程序中类的用法
.:专门用来访问属性,本质操作的就是__dict__
Heros. birthplace #等于经典类的操作Heros.__dict__['birthplace']
Heros. birthplace='王者荣耀' #等于经典类的操作Heros.__dict__['birthplace']='王者荣耀'
Heros.x=1 #等于经典类的操作Heros.__dict__['x']=1
del Heros.x #等于经典类的操作Heros.__dict__.pop('x') #程序中的对象
#调用类,或称为实例化,得到对象
hero1=Heros()
hero2=Heros()
hero3=Heros() #如此,hero1、hero2、hero3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__
#注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值
class Heros:
......
def __init__(self,name,atk,hp):
self.name=name
self.atk=atk
self.hp=hp
...... hero1=Heros('盖伦',200,200) #先调用类产生空对象hero1,然后调用Heros.__init__(hero1,'盖伦',200,200)
hero2=Heros('诺克萨斯之手',150,200)
hero3=Heros('托儿索',100,200) #程序中对象的用法
#执行__init__,hero1.name='盖伦',很明显也会产生对象的名称空间
hero1.__dict__
{'name': '盖伦', 'atk': 200, 'hp': 200} hero1.name #hero1.__dict__['name']
hero2.name='诺克萨斯之手' #hero2.__dict__['name']='诺克萨斯之手'

PS:

1. 站的角度不同,定义出的类是截然不同的,

2. 现实中的类并不完全等于程序中的类,比如现实中的公司类,在程序中有时需要拆分成部门类,业务类...... 

3. 有时为了编程需求,程序中也可能会定义现实中不存在的类,比如策略类,现实中并不存在,但是在程序中却是一个很常见的类

#python为类内置的特殊属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)

三、类的属性查找

类有两种属性:数据属性和函数属性

  1. 类的数据属性是所有对象共享的

  2. 类的函数属性是绑定给对象用的

class Heros:
birthplace='王者荣耀'
def attcck(self): #普通的攻击技能
pass hero1=Heros()
hero2=Heros()
hero3=Heros()
#类的数据属性是所有对象共享的,id都一样
print(id(Heros.birthplace)) print(id(hero1.birthplace))
print(id(hero2.birthplace))
print(id(hero3.birthplace)) '''
4651296
4651296
4651296
4651296
''' #类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样
#ps:id是python的实现机制,并不能真实反映内存地址,如果有内存地址,还是以内存地址为准
print(Heros.attcck)
print(hero1.attcck)
print(hero2.attcck)
print(hero3.attcck) '''
<function Heros.attcck at 0x0000000001E81730>
<bound method Heros.attcck of <__main__.Heros object at 0x0000000001E7E7F0>>
<bound method Heros.attcck of <__main__.Heros object at 0x0000000001E7E780>>
<bound method Heros.attcck of <__main__.Heros object at 0x0000000001E7E828>>
'''

在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常

四、 绑定到对象的方法的特殊之处

#改写
class Heros:
def __init__(self,name,atk,hp):
self.name=name
self.atk=atk
self.hp=hp
def attcck(self,enemy): # 普通的攻击技能
  print("%s攻击%s"%(self,enemy)) hero1=Heros('盖伦',200,200) #先调用类产生空对象hero1,然后调用Heros.__init__(hero1,'盖伦',200,200)
hero2=Heros('诺克萨斯之手',150,200)
hero3=Heros('托儿索',100,200)

类中定义的函数(没有被任何装饰器装饰的)是类的函数属性,类可以使用,但必须遵循函数的参数规则,有几个参数需要传几个参数:

Heros.attcck(hero1,hero2)  #  盖伦攻击诺手
Heros.attcck(hero2,hero3) # 诺手攻击儿索
Heros.attcck(hero3,hero1) # 儿索攻击盖伦

类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法

强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法__init__也是一样的道理):

hero1.attcck(hero2)  #  盖伦攻击诺手
hero2.attcck(hero3) # 诺手攻击儿索
hero3.attcck(hero1) # 儿索攻击盖伦

注意:绑定到对象的方法的这种自动传值的特征,决定了在类中定义的函数都要默认写一个参数self,self可以是任意名字,但是约定俗成地写出self。

类即类型

  python中一切皆为对象,且python3中类与类型是一个概念,类型就是类

#类型dict就是类dict
>>> list
<class 'list'> #实例化的到3个对象l1,l2,l3
>>> l1=list()
>>> l2=list()
>>> l3=list() #三个对象都有绑定方法append,是相同的功能,但内存地址不同
>>> l1.append
<built-in method append of list object at 0x10b482b48>
>>> l2.append
<built-in method append of list object at 0x10b482b88>
>>> l3.append
<built-in method append of list object at 0x10b482bc8> #操作绑定方法l1.append(3),就是在往l1添加3,绝对不会将3添加到l2或l3
>>> l1.append(3)
>>> l1
[3]
>>> l2
[]
>>> l3
[]
#调用类list.append(l3,111)等同于l3.append(111)
>>> list.append(l3,111) #l3.append(111)
>>> l3
[111]

python3全栈开发-面向对象、面向过程的更多相关文章

  1. python3全栈开发-面向对象的三大特性(继承,多态,封装)之继承

    一 .初识继承 1.什么是继承 继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类. 特点: 子类会“”遗传”父类的属 ...

  2. python3 全栈开发 -- 面向对象 类的组合和封装

    一.类的组合 1.什么是组合 组合:描述的是类与类之间的关系,是一种什么有什么关系 一个类产生的对象,该对象拥有一个属性,这个属性的值是来自于另外一个类的对象 2.什么是继承(回顾一下) 继承:描述的 ...

  3. python全栈开发-面向对象-初识

    python_16_day 函数总结: https://www.processon.com/view/link/5b718274e4b0555b39e1055f 面向过程的程序设计的核心是过程(流水线 ...

  4. python3全栈开发-补充UDP的套接字、操作系统、并发的理论基础

    一.基于UDP的套接字 udp套接字简单示例 import socket ip_port=('1.1.1.1',8181) BUFSIZE=1024 udp_server_client=socket. ...

  5. python 3全栈开发-面向对象之绑定方法(classmethod与staticmethod的区别)、多态、封装的特性property

    一.面向对象绑定方法 一.类中定义的函数分成两大类 1.绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入): 1. 绑定到类的方法:用classmethod装饰器装饰的方法. 为类量身定制 ...

  6. python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法

    一.内置函数补充 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() print(isinstan ...

  7. python3全栈开发-socket编程

    一. 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务端为你提供视 ...

  8. python3全栈开发-并发编程,多进程的基本操作

    一 .multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程. ...

  9. python3全栈开发-多进程的守护进程、进程同步、生产者消费者模式(重点)

    一.守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes a ...

随机推荐

  1. mysql存储过程(查询数据库内表 游标循环 if判断 插入别的表内)

    BEGIN declare f_age int;DECLARE incode1 VARCHAR(100);DECLARE incode2 VARCHAR(100);DECLARE incode3 VA ...

  2. bat脚本:windows下一键启动zookeeper+kafka

    bat脚本:windows下一键启动zookeeper+kafka 把下面两行代码存为bat文件,双击执行即可.注意更改相应的目录 这里用ping来控制时间(先zookeeper,ping 4 次后 ...

  3. 笔记:Eclipse 安装 m2eclipse 插件

    M2eclipse 插件 Eclipse 下一款十分强大的 Maven 插件,可以访问 http://m2eclipse.sonatype.org 了解更多该项目的信息,如果需要安装该插件可以按照如下 ...

  4. 二分查找(binary search)java实现及时间复杂度

    概述 在一个已排序的数组seq中,使用二分查找v,假如这个数组的范围是[low...high],我们要的v就在这个范围里.查找的方法是拿low到high的正中间的值,我们假设是m,来跟v相比,如果m& ...

  5. Python十题(第2课)

    一.天天向上的力量 C 一年365天,以第1天的能力值为基数,记为1.0.当好好学习时,能力值相比前一天提高N‰:当没有学习时,由于遗忘等原因能力值相比前一天下降N‰.每天努力或放任,一年下来的能力值 ...

  6. ansible自动化运维

    ansible 系统架构 ansible简介 ansible是新出现的自动化运维工具,ansible是一个配置管理和应用部署工具,基于Python开发,集合了众多运维工具(puppet.cfengin ...

  7. 如何正确使用Java异常处理机制

    文章来源:leaforbook - 如何正确使用Java异常处理机制作者:士别三日 第一节 异常处理概述 第二节 Java异常处理类 2.1 Throwable 2.1.1 Throwable有五种构 ...

  8. [css 揭秘]:CSS编码技巧

    CSS编码技巧 我的github地址:https://github.com/FannieGirl/ifannie 喜欢的给我一个星吧 尽量减少代码重复 尽量减少改动时需要编辑的地方 当某些值相互依赖时 ...

  9. 使用ADO.NET查询和操作数据

    使用ADO.NET查询和操作数据 StringBuilder类: 用来定义可变字符串StringBuilder sb = new StringBuilder("");//追加字符串 ...

  10. iOS App 启动性能优化

    1. App启动过程 解析Info.plist 加载相关信息,例如如闪屏 沙箱建立.权限检查 Mach-O加载 如果是胖二进制文件,寻找合适当前CPU类别的部分 加载所有依赖的Mach-O文件(递归调 ...