第二十六篇 面向对象初识

一. 三大编程范式

前面学完了Python的基本语法,能写Python代码, 而且可以处理工作中的一些问题,今天开始就要进入面向对象的学习了。首先,了解下三大编程范式,编程范式就是编程方法论,表明的是一种编程风格。

切记:三种编程风格没有好坏之分,有分别的是使用不同风格的人。

1. 面向过程编程

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

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

缺点是:一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得是大改,改一个组件,牵一发而动全身。

应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。

2. 函数式编程

  包括数学层面的函数和代码层面的函数。

3.面向对象编程

  核心是对象二字,(要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。面向对象的程序设计好比如来设计西游记,如来要解决的问题是把经书传给东土大唐,如来想了想解决这个问题需要四个人:唐僧,沙和尚,猪八戒,孙悟空,每个人都有各自的特征和技能(这就是对象的概念,特征和技能分别对应对象的数据属性和方法属性),然而这并不好玩,于是如来又安排了一群妖魔鬼怪,为了防止师徒四人在取经路上被搞死,又安排了一群神仙保驾护航,这些都是对象。然后取经开始,师徒四人与妖魔鬼怪神仙交互着直到最后取得真经。如来根本不会管师徒四人按照什么流程去取),对象是特征与技能的结合体,基于面向对象设计程序就好比在创造一个世界,你就是这个世界的上帝,存在的皆为对象,不存在的也可以创造出来,与面向过程机械式的思维方式形成鲜明对比,面向对象更加注重对现实世界的模拟,是一种“上帝式”的思维方式。

优点:

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

缺点:

  1. 编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极容易出现过度设计的问题。一些扩展性要求低的场景使用面向对象会徒增编程难度,比如管理linux系统的shell脚本就不适合用面向对象去设计,面向过程反而更加适合。

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

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

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

二.编程进化论

1. 编程最开始就是无组织无结构,从简单控制流中按步写指令

2. 从上述的指令中提取重复的代码块或逻辑,组织到一起(比如,定义了一个函数),便实现了代码重用,且代码从无结构走向了结构化,创建程序的过程变得更具逻辑性。

3. 定义函数都是独立于函数外定义变量,然后作为参数传递给函数,这意味着:数据与动作是分离的。

4. 如果把数据和动作内嵌到一个结构(函数或类)里面,那么就有了一个“对象矽统”(对象就是数据与函数整合到一起的产物)。

三. 颠覆一下面向对象

def dog(name,gender,type):
    # 狗的动作
    def jiao(dog):
        print(‘一条狗[%s],汪汪汪‘ % dog[‘name‘])
    def chi_shi(dog):
        print(‘一条[%s] 正在吃屎‘ % dog[‘type‘])
    # 定义了init函数,作用是初始化狗,初始化了狗的特征和动作
    def init(name,gender,type):
        dog1 = {
            # 初始化狗的特征
            ‘name‘:name,
            ‘gender‘: gender,
            ‘type‘: type,
            # 初始化狗的动作
            ‘jiao‘:jiao,
            ‘chi_shi‘:chi_shi,
        }
        return dog1
    return init(name,gender,type)

# d1,d2就是一个个具体的对象,是一条真真实实的狗
d1=dog(‘xiaohei‘,‘母‘,‘中华田园犬‘)
d2=dog(‘heimei‘,‘母‘,‘藏敖‘)
print(d1)
print(d2)
d1[‘jiao‘](d1)
d2[‘chi_shi‘](d2)
# 结果
{‘name‘: ‘xiaohei‘, ‘gender‘: ‘母‘, ‘type‘: ‘中华田园犬‘, ‘jiao‘: <function dog.<locals>.jiao at 0x00C11B28>, ‘chi_shi‘: <function dog.<locals>.chi_shi at 0x00C11AE0>}
{‘name‘: ‘heimei‘, ‘gender‘: ‘母‘, ‘type‘: ‘藏敖‘, ‘jiao‘: <function dog.<locals>.jiao at 0x00C11A50>, ‘chi_shi‘: <function dog.<locals>.chi_shi at 0x00C11A98>}
一条狗[xiaohei],汪汪汪
一条[藏敖] 正在吃屎

示例

# 如何描述一个对象?
# 1.描述它的特征
# 2.描述它的动作
# 所以对象,就是特征与动作的结合

# 如何描述一个类?
# 1. 描述他的特征
# 2. 描述他的动作
# 3. 把具有共性的特征和动作提取出来,抽象成一个类,比如人类, 植物等,就是一个类

# 对象就是从类里抽象出的一个具体的个体, 类所具有的全部特征和动作,这个具体的对象都具有。
# 比如某个具体的人,你媳妇,她就具有人类所有的特征和动作。

为什么说是颠覆一下面向对象呢?

因为常规认为面向对象都是class类,而此处却用的是def函数,而且它的设计思想就是面向对象的思想。

三.类与对象

1. 什么是类?

把一类事物的相同的特征和动作整合到一起就是类。类是一个抽象的概念。

2. 什么是对象?

对象就是基于类而创建的一个具体的事物,具体真实的存在。对象也是特征和动作整合到一起的。

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

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

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

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

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

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

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

好啦,下面看看怎么一步步接近真相的。

# 需求
# 定义一个学校类
# 特征:name(学校名字), addr(学校地址), type(学校类型)
# 动作:考试,招生,开除奖励

 1 # 原始方法
 2
 3 # 1. 特征
 4 school1 = {
 5     ‘name‘:‘人大‘,
 6     ‘address‘:"海淀",
 7     ‘type‘:‘985‘
 8 }
 9
10 # 学校可以完成的动作
11 def kaoshi(school):
12     print("%s 学校正在考试" %school[‘name‘])
13
14 def zhaosheng(shcool):
15     print("%s %s 学校正在招生" %(school(‘type‘),school[‘name‘]))

原始方法

 1 # 上面一个基本的学校类就定义好了,但是存在一个问题,就是可能来了一条狗也能调用考试的方法,
 2 # 所以需要进化,把属性和动作整合到一起,到目前为止通过作用域的方式可以完成
 3
 4 def school():
 5     # 1. 特征
 6     school1 = {
 7         ‘name‘: ‘人大‘,
 8         ‘address‘: "海淀",
 9         ‘type‘: ‘985‘
10     }
11
12     # 学校可以完成的动作
13     def kaoshi(school):
14         print("%s 学校正在考试" % school[‘name‘])
15
16     def zhaosheng(shcool):
17         print("%s %s 学校正在招生" % (school(‘type‘), school[‘name‘]))

第一次进化

 1 # 这里虽然完成了把属性和动作的整合,保证外部来的那条狗是无法调用了学校了,但是,又出现个新问题,
 2 # 就是写死了一个对象school1,有没有什么方法可以实现多个对象呢?
 3
 4 def school(name,addr,typer):
 5     # 1. 特征
 6     school1 = {
 7         ‘name‘: name,   # 这里就不能写死了,需要一个变量替代,变量从外部传入
 8         ‘address‘: addr,
 9         ‘type‘: typer
10     }
11
12     # 学校可以完成的动作
13     def kaoshi(school):
14         print("%s 学校正在考试" % school[‘name‘])
15
16     def zhaosheng(shcool):
17         print("%s %s 学校正在招生" % (school(‘type‘), school[‘name‘]))

第二次进化

 1 # 这里虽然完成了把属性和动作的整合,保证外部来的那条狗是无法调用了学校了,但是,又出现个新问题,
 2 # 就是写死了一个对象school1,有没有什么方法可以实现多个对象呢?
 3
 4 def school(name,addr,typer):
 5     # 1. 特征
 6     school1 = {
 7         ‘name‘: name,   # 这里就不能写死了,需要一个变量替代,变量从外部传入
 8         ‘address‘: addr,
 9         ‘type‘: typer
10     }
11
12     # 学校可以完成的动作
13     def kaoshi(school):
14         print("%s 学校正在考试" % school[‘name‘])
15
16     def zhaosheng(shcool):
17         print("%s %s 学校正在招生" % (school(‘type‘), school[‘name‘]))

第三次进化

 1 1 def school(name,addr,typer):
 2  2
 3  3     # 学校可以完成的动作
 4  4     def kaoshi(school):
 5  5         print("%s 学校正在考试" % school[‘name‘])
 6  6
 7  7     def zhaosheng(school):
 8  8         print("%s %s 学校正在招生" % (school[‘type‘], school[‘name‘]))
 9  9
10 10     # 1. 特征
11 11     sch = {
12 12         ‘name‘: name,   # 这里就不能写死了,需要一个变量替代,变量从外部传入
13 13         ‘address‘: addr,
14 14         ‘type‘: typer,
15 15         # 在特征里实现对象和动作的绑定
16 16         ‘kao_shi‘:kaoshi,
17 17         ‘zhao_sheng‘:zhaosheng
18 18     }
19 19     # 对象生成了,需要返回才可以
20 20     return sch
21 21
22 22 # 生成对象s1人大
23 23 s1 = school(‘人大‘,‘海淀‘,‘985‘)
24 24 print(s1)
25 25 # 返回的是字典
26 26 # {‘name‘: ‘人大‘, ‘address‘: ‘海淀‘, ‘type‘: ‘985‘, ‘kao_shi‘: <function school.<locals>.kaoshi at 0x007E1AE0>, ‘zhao_sheng‘: <function school.<locals>.zhaosheng at 0x007E1A50>}
27 27
28 28 # 可以通过生成的对象来调学校的名字了
29 29 print(s1[‘name‘])
30 30 # 人大
31 31
32 32 # 可以看这个学校有什么动作
33 33 print(s1[‘kao_shi‘])   # <function school.<locals>.kaoshi at 0x003F1AE0>
34 34
35 35 print(s1[‘zhao_sheng‘])  # <function school.<locals>.zhaosheng at 0x003F1A50>
36 36
37 37
38 38 # 如果想让新生成的s1人大这个对象来执行学校的考试动作
39 39 s1[‘kao_shi‘](s1)
40 40 # 人大 学校正在考试
41 41
42 42 # 如果想让新生成的s1人大这个对象来执行学校的招生动作
43 43 s1[‘zhao_sheng‘](s1)
44 44 # 985 人大 学校正在招生

第四次进化

‘‘‘
上面的程序已经可以完成功能了,但是还是不够好,

‘‘‘

def school(name,addr,typer):
    # 让他变的更好,要在局部作用域里,定义一个init的函数
    def init(name,addr,typer):
        # 1. 特征
        sch = {
            ‘name‘: name,  # 这里就不能写死了,需要一个变量替代,变量从外部传入
            ‘address‘: addr,
            ‘type‘: typer,
            # 在特征里实现对象和动作的绑定
            ‘kao_shi‘: kaoshi,
            ‘zhao_sheng‘: zhaosheng
        }
        # 对象生成了,需要返回才可以
        return sch
    # 学校可以完成的动作
    def kaoshi(school):
        print("%s 学校正在考试" % school[‘name‘])

    def zhaosheng(school):
        print("%s %s 学校正在招生" % (school[‘type‘], school[‘name‘]))

# 先 看下结构,代码就变得整洁了

第五次进化

# 但是,又有 一个问题,执行school函数,函数体内没有任何运行,而我们的目的是一执行school函数,立马回返回一个真实存在的s1的对象,
# 那怎么才能生成这个对象呢?而做这件事的就是init函数,所以只需要执行school函数的时候,运行init函数就行了呗。所以加上init(),另外,
# 函数运行,需要返回结果哦,所以是 return init()

def school(name,addr,typer):
    # 让他变的更好,要在局部作用域里,定义一个init的函数
    def init(name,addr,typer):
        # 1. 特征
        sch = {
            ‘name‘: name,  # 这里就不能写死了,需要一个变量替代,变量从外部传入
            ‘address‘: addr,
            ‘type‘: typer,
            # 在特征里实现对象和动作的绑定
            ‘kao_shi‘: kaoshi,
            ‘zhao_sheng‘: zhaosheng
        }
        # 对象生成了,需要返回才可以
        return sch
    # 学校可以完成的动作
    def kaoshi(school):
        print("%s 学校正在考试" % school[‘name‘])

    def zhaosheng(school):
        print("%s %s 学校正在招生" % (school[‘type‘], school[‘name‘]))
    # 运行init()函数,并返回运行结果
    return init(name,addr,typer)

s1 = school(‘清华‘,‘五道口‘,‘公立‘)
print(s1)
s2 = school(‘人大‘,‘魏公村‘,‘公立‘)
print(s2)
s2[‘zhao_sheng‘](s2)

第六次进化

上面的实现过程就是一个面向对象的设计过程思想

四. 面向对象设计(Object oriented design)

所谓面向对象设计:就是将一类事物的具体数据和动作整合到一起,即面向对象设计

面向对象设计(OOD)不会特别要求面向对象编程语言。事实上,OOD可以由纯结构化语言来实现(比如C)。但如果想要构造局对对象性质和特点的数据类型,就需要在程序上作更多努力。

五. 面向对象编程(object-oriented programming)

所谓面向对象编程:就是定义类+实例/对象的方法去实现面向对象的设计

# 用面向对象编程独有的语法class去实现面向对象设计
# 最直观的展示面向对象展示

‘‘‘
这段程序里有两个地方要注意:第一个是class,第二个是方法后面的self,这个self到底是什么东东?
‘‘‘

关于self,其实说白了就是对象自己。

对于函数来说,就是一个位置参数,函数在运行的时间,需要把自己传进来。

关于self,其实说白了就是对象自己。

对于函数来说,就是一个位置参数,函数在运行的时间,需要把自己传进来。
用上面的示例可以清楚的看到

def school(name,addr,typer):
    def init(name,addr,typer):
        sch = {
            ‘name‘: name,
            ‘address‘: addr,
            ‘type‘: typer,
            ‘kao_shi‘: kaoshi,
            ‘zhao_sheng‘: zhaosheng
        }
        return sch
    def kaoshi(school):
        print("%s 学校正在考试" % school[‘name‘])

    def zhaosheng(school):
        print("%s %s 学校正在招生" % (school[‘type‘], school[‘name‘]))

# 替换成self后,原理就是这样。
def school(name,addr,typer):
    def init(name,addr,typer):
        sch = {
            ‘name‘: name,
            ‘address‘: addr,
            ‘type‘: typer,
            ‘kao_shi‘: kaoshi,
            ‘zhao_sheng‘: zhaosheng
        }
        return sch
    def kaoshi(self):
        print("%s 学校正在考试" % self[‘name‘])

    def zhaosheng(self):
        print("%s %s 学校正在招生" % (self[‘type‘], self[‘name‘]))

关于self

小总结

1. 有人说,只有class定义类才是面向对象,def定义函数就是函数相关的,跟面向对象没关系----错的哦,上面已经很清楚的通过def展示了面向对象。

2. 一门面向对象语言不一定会强制你写面向对象(OO)方面的程序。例如,C++可以被认为“更好的C”;而java则要求万物皆类,此外,还规定,一个源文件对应一个类定义。

3.然而,在Python中,类和面向对象编程OOP都不是日常编程所必须的。尽管它从一开始设计就是面向对象的,并且结构上支持OOP,但Python没有限定或要求你在你的应用中写OO的代码。

  Python是面向对象语言,提供了丰富的class方面的内容。

4. 用面向对象语言写程序,和一个程序的设计是面向对象的,两者是八竿子打不着的两码事。

原文地址:https://www.cnblogs.com/victorm/p/9308762.html

时间: 2024-10-08 12:06:06

第二十六篇 面向对象初识的相关文章

Python之路(第二十六篇) 面向对象进阶:内置方法

一.__getattribute__ object.__getattribute__(self, name) 无条件被调用,通过实例访问属性.如果class中定义了__getattr__(),则__getattr__()不会被调用(除非显示调用或引发AttributeError异常) class Foo: ? def __init__(self,x): self.x = x ? def __getattr__(self, item): print("执行__getattr__") ?

第二十六篇:USB3.0高带宽ISO(48KBytes/125us)实战

USB3.1技术已经推出, 10Gbps的速率足以满足数据, HD视频传输的要求. 要步入USB3.1的研发, 还得将USB3.0的基础打扎实. 微软提供的SUPER MUTT只包含一个接口0, 其下有两个ALT, ALT 1与ALT 2, 分别包含了两对ISO IN/OUT端点, 不过, 只有ALT 2下的ISO OUT EP的bMaxBurst为1, 而其它三个ISO EP的bMaxBurst均为0, 而所有的ISO EP的Mult均为0. 即只有一个ISO EP支持2KBytes/125u

第二十六篇 知识点总结

虽然不是周末,但是这次我有空就来整理并回顾一下这一周所学的知识.... 这一周,我主要学习到 了Java中的一些基础知识,其中包括:接口.类.抽象类.继承.构造函数.方法重写.方法重载.自动转型.多态.引用传递: 下面 ,我就来一一总结一下,首先 先谈一下接口,什么是接口? Java接口 是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能). 它主要使用的关键字是----interface

第二十六篇 jQuery 学习8 遍历-父亲兄弟子孙元素

jQuery 学习8 遍历-父亲兄弟子孙元素 jQuery遍历,可以理解为"移动",使用"移动"还获取其他的元素. 什么意思呢?老师举一个例子: 班上30位同学,我是新来负责教这个班学生的老师,但我不认识所有学生,只认识上学期教过的几位同学.比如小明.我们再用一小串代码来作解释: <body> <span id="ming">我是小明</span> <span>我坐在小明后面,我叫李四</sp

python全栈开发基础【第二十六篇】(concurrent.futures模块、协程、Greenlet、Gevent)

注意 1.不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 2.只要你用并发,就会有锁的问题,但是你不能一直去自己加锁吧那么我们就用QUEUE,这样还解决了自动加锁的问题由Queue延伸出的一个点也非常重要的概念.以后写程序也会用到这个思想.就是生产者与消费者问题 一.Python标准模块--concurrent.futures(并发未来) concurent.future模块需要了解的 1.concurent

第二十六篇:两个SOUI新控件 ---- SListView和SComboView(借用Andorid的设计)

SOUI原来实现的SListBoxEx的效率一直是我对SOUI不太满意的地方.包括后来网友实现的SListCtrlEx. 这类控件为每一个列表项创建一个SWindow来容纳数据,当数据量比较大(10000+)时,一方面内存消耗会很严重:另一方面列表数据初始化也需要大量的时间. 今年开始转型做Android开发.大家都知道Android开发APP和PC上开发APP相比要简单很多,其中我个人体会最深的就是Android的ListView控件. 在Android中,ListView中列表项的显示采用控

第二十六篇:通知中心 NSNotificationCenter

1.通知中心(NSNotificationCenter) ?每一个应用程序都有一个通知中心(NSNotificationCenter)实例,专门负责协助不同对象之间的消息通信 ?任何一个对象都可以向通知中心发布通知(NSNotification),描述自己在做什么.其他感兴趣的对象(Observer)可以申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知 2.通知(NSNotification) >一个完整的通知一般包含3个属性: - (NSString*)name; // 通

第二十六篇、因为自定item(nav)而使系统右滑返回手势失效的解决方法

@interface ViewController () <uigesturerecognizerdelegate> @[email protected] ViewController - (void)viewDidLoad { [super viewDidLoad]; // 自定义返回按钮 UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 44, 44)]; [button setTitle:@"王

第二十六篇 圆满

"圆满"是我们所有人都想达到的一种最佳状态.因为在人类世界中很少有人达到这种状态,所以我们才非常向往.当然以上所说的"圆满",指的是一个人达到了创造者当初对自身生命各种能力的设计预期,这就是我所表达的一个人类生命的圆满状态. 我们如今虽然还没有能力达到那样的圆满状态,但是我们可以通过自身的不断努力朝着那样的方向去提升与发展,这是我们作为人类生命的第一人生目标.只有完成了这第一人生目标,我们才有机会往更高的领域去进展.希望亲人们一定要清楚我们人类生命还有很大的发展空间