初识面向对象
Posted zmc940317
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识面向对象相关的知识,希望对你有一定的参考价值。
面向对象VS函数式编程VS面向对象
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点:极大的降低了写程序的复杂度,只需要顺着执行的步骤,垒代码就可以.
缺点:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身.
应用:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
函数式编程就是将某功能封装到函数中,日后便无需编写,仅调用函数即可.
优点:增强代码的重要性和可读性,简单便捷.
缺点:如果要写的程序有多个函数,但是调用的参数是一个,这样会造成代码的重复.
面向对象就是对函数进行封装和分类,让开发"更好更快更强"...
优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏
创建类和对象
在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是"类",对象就是这一类事物中具体的一个.
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能.
对象则是根据模板创建的实例,通过实例对象可以执行类中的函数.
注意:类中的函数第一个参数必须是 self (详见下面的三大特性之封装).
在类中,类中定义的函数叫做"方法"
#面向对象编程的格式 #定义了一个类 class Foo: #Foo--类名 #在类中编写了一个"方法" def func1(self): #func1--函数名 print("func1") #调用: obj = Foo() #创建了一个对象. obj.func1() #通过对象调用其中一个方法.
面向对象的三大特性
面向对象的三大特性: 封装 , 继承 , 多态
一.封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容.
所以,在使用面向对象的封装特性时,需要:
. 将内容封装到某处
. 从某处调用被封装的内容
第一步:将内容封装到某处
self 是一个形式参数,当执行 obj1 = Foo("张三",18)时,self 等于 obj1
当执行 obj2 = Foo(‘alex‘, 78 ) 时,self 等于 obj2
所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性.
在内存里类似于下图来保存。
第二步 : 从某处调用被封装的内容
调用被封装的内容时,有两种情况:
.通过对象直接调用
.通过self间接调用
1、通过对象直接调用被封装的内容
上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名
class Foo: def __init__(self,name,age): self.name = name self.age = age obj1 = Foo("张三",18) print(obj1.name) #直接调用obj1对象的name的属性 print(obj1.age) #直接调用obj1对象的age的属性 obj2 = Foo("李四",38) print(obj2.name) #直接调用obj2对象的name的属性 print(obj2.age) #直接调用obj2对象的name的属性
2.通过 self 间接调用被封装的内容
执行类中的方法时,需要同过 self 讲解调用被封装的内容.
class Foo: def __init__(self,name,age): self.name = name self.age = age def func(self): print(self.name) print(self.age) obj1 = Foo("张三",18) obj1.func() #Python默认会将obj1传给self参数,即:obj1.func(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 张三;self.age 是 18 obj2 = Foo("李四",38) obj2.func() # Python默认会将obj2传给self参数,即:obj1.func(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 李四 ; self.age 是38 结果: 张三 18 李四 38
所以,对于面向对象的封装来说,其实就是使用构造方法将内容封装待 对象 中,然后通过对象之间或者 self 间接获取封装的内容
练习:输入如下信息 ● 小明 , 20岁,男,上山去砍柴 ● 小明,20岁,男,开车去东北 ● 小明,20岁,男,最爱大保健
● 老李,40岁,男,上山去砍柴 ● 老李,40岁,男,开车去东北 ● 老李,40岁,男,最爱大保健 ........................... def kanchai(name, age, gender): print "%s,%s岁,%s,上山去砍柴" %(name, age, gender) def qudongbei(name, age, gender): print "%s,%s岁,%s,开车去东北" %(name, age, gender) def dabaojian(name, age, gender): print "%s,%s岁,%s,最爱大保健" %(name, age, gender) kanchai(‘小明‘, 20, ‘男‘) qudongbei(‘小明‘, 20, ‘男‘) dabaojian(‘小明‘, 20, ‘男‘) kanchai(‘老李‘, 40, ‘男‘) qudongbei(‘老李‘, 40, ‘男‘) dabaojian(‘老李‘, 40, ‘男‘) class Foo: def __init__(self, name, age ,gender): self.name = name self.age = age self.gender = gender def kanchai(self): print "%s,%s岁,%s,上山去砍柴" %(self.name, self.age, self.gender) def qudongbei(self): print "%s,%s岁,%s,开车去东北" %(self.name, self.age, self.gender) def dabaojian(self): print "%s,%s岁,%s,最爱大保健" %(self.name, self.age, self.gender) xiaoming = Foo(‘小明‘, 20, ‘男‘) xiaoming.kanchai() xiaoming.qudongbei() xiaoming.dabaojian() laoli = Foo(‘老李‘, 40, ‘男‘) laoli.kanchai() laoli.qudongbei() laoli.dabaojian()
上述对比可以看出,如果使用函数式编程,需要在每次执行函数时传入相同的参数,如果参数多的话,又需要粘贴复制了... ;而对于面向对象只需要在创建对象时,将所有需要的参数封装到当前对象中,之后再次使用时,通过self间接去当前对象中取值即可。 |
二 . 继承
继承可以提高代码的重用性
继承 : 面向对象中的继承和现实中的继承是相同的,都是 : 子可以继承父亲的内容.
#基本写法 class SuperBase: def f3(self): print(‘f3‘) class Base(SuperBase): # 父类,基类 def f2(self): print(‘f2‘) class Foo(Base): # 子类,派生类 def f1(self): print(‘f1‘) obj = Foo() obj.f1() obj.f2() obj.f3() # 原则:现在自己类中找,没有就去父类 结果: f1 f2 f3
所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。
#练习一 class Base: def f1(self): print(‘base.f1‘) def f3(self): print(‘foo.f3‘) class Foo(Base): def f2(self): print(‘foo.f2‘) self.f3() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. obj = Foo() obj.f2() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. 结果: foo.f2 base.f1 foo.f3 #练习二 class Base: def f1(self): print(‘base.f1‘) def f3(self): self.f1() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. print(‘base.f3‘) class Foo(Base): def f1(self): print(‘foo.f1‘) def f2(self): print(‘foo.f2‘) self.f3() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. obj = Foo() obj.f2() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. # foo.f2 # foo.f1 # base.f3 obj2 = Base() obj2.f3() # base.f1 # base.f3
总结: self 是哪一个类的对象,那么就从该类开始找,没有就去找父类
多继承
1.python的类可以继承多个类,java 和 C# 只能继承一个类
2.类在继承的时候,先找左边的父类.
class Base1: def f1(self): print(‘base1.1‘) def f2(self): print(‘base1.f2‘) class Base2: def f1(self): print(‘base2.f1‘) def f2(self): print(‘base2.f2‘) def f3(self): print(‘base2.f3‘) self.f1() class Foo(Base1, Base2): def f0(self): print(‘foo.f0‘) self.f3() obj = Foo() obj.f0() 结果: foo.f0 base2.f3 base1.1
总结:
1.多继承,先找左边
2.在继承中,只能子找父,不能父找子
3.self 到底是谁? self 是哪个类的对象名那么就从该类开始找,没有就去找父类.
三 . 多态
Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。也就是说,在python中,我们是不用考虑多态的问题的.
以上是关于初识面向对象的主要内容,如果未能解决你的问题,请参考以下文章