1, 面向对象初识
面向过程的程序设计的核心是过程 (流水线式思维), 过程即解决问题的步骤, 面向过程的设计就好比精心设计好一条流水线, 考虑周全什么时候处理什么东西.
优点是: 极大的降低了写程序的复杂度, 只需要顺着要执行的步骤, 堆叠代码即可.
缺点是: 一套流水线或者流程就是用来解决一个问题, 代码牵一发而动全身.
应用场景: 一旦完成基本很少改变的场景, 著名的例子有 Linux 內核, git, 以及 Apache HTTP Server 等.
面向对象的程序设计的核心是对象 (上帝式思维), 要理解对象为何物, 必须把自己当成上帝, 上帝眼里世间存在的万物皆为对象, 不存在的也可以创造出来. 面向对象的程序设计好比如来设计西游记, 如来要解决的问题是把经书传给东土大唐, 如来想了想解决这个问题需要四个人: 唐僧, 沙和尚, 猪八戒, 孙悟空, 每个人都有各自的特征和技能 (这就是对象的概念, 特征和技能分别对应对象的属性和方法), 然而这并不好玩, 于是如来又安排了一群妖魔鬼怪, 为了防止师徒四人在取经路上被搞死, 又安排了一群神仙保驾护航, 这些都是对象. 然后取经开始, 师徒四人与妖魔鬼怪神仙互相缠斗着直到最后取得真经. 如来根本不会管师徒四人按照什么流程去取.
面向对象的程序设计的.
优点是: 解决了程序的扩展性. 对某一个对象单独修改, 会立刻反映到整个体系中, 如对游戏中一个人物参数的特征和技能修改都很容易.
缺点: 可控性差, 无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果, 面向对象的程序一旦开始就由对象之间的交互解决问题, 即便是上帝也无法预测最终结果. 于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现, 一刀砍死 3 个人, 这个游戏就失去平衡.
应用场景: 需求经常变化的软件, 一般需求的变化都集中在用户层, 互联网应用, 企业内部软件, 游戏等都是面向对象的程序设计大显身手的好地方.
在 python 中面向对象的程序设计并不是全部.
面向对象编程可以使程序的维护和扩展变得更简单, 并且可以大大提高程序开发效率 , 另外, 基于面向对象的程序可以使它人更加容易理解你的代码逻辑, 从而使团队开发变得更从容.
了解一些名词: 类, 对象, 实例, 实例化
类: 具有相同特征的一类事物 (人, 狗, 老虎)
对象 / 实例: 具体的某一个事物 (隔壁阿花, 楼下旺财)
实例化: 类 --> 对象的过程 (这在生活中表现的不明显, 我们在后面再慢慢解释)
面向对象特点:
1, 函数封装一个功能, 而面向对象封装多个相关的功能.
2, 面向对象抽象, 它是一种思想, 站在上帝的角度去理解它.
3, 程序可扩展, 对象都是一个个独立的. 耦合性, 差异性.
实例化过程内部进行了三个阶段:
1, 在内存中开辟了一个对象空间.
2, 自动执行类中的__init__方法, 并且将对象空间自动传给 self 参数, 其他的参数手动传入.
3, 执行__init__方法, 给对象空间封装相应的属性.
2, 类的相关知识
声明
- def func(ars):
- "函数体"
- func()
声明函数
class 类名:
- "类体"
- # 我们创建一个类
- class Data:
- pass
声明一个类
- class Person: # 定义一个类
- role = "person" # 人的角色属性都是人
- def walk(self): # 人都可以走路, 也就是有一个走路的方法, 也叫动态属性
- print("peerson is walking...")
- print(Person.role) # 查看人的 felo 属性
- print(Person.walk) # 引用人的走路方法, 注意, 这里不是在调用
实例化的过程就是类 --> 对象的过程
原本我们只有一个 Person 类, 在这个过程中, 产生了一个 egg 对象, 有自己具体的名字, 攻击力和生命值.
语法: 对象名 = 类名 (参数)
self
self: 在实例化时自动将对象 / 实例本身传给__init__的第一个参数, 你也可以给他起个别的名字, 但是正常人都不会这么做.
因为你瞎改别人就不认识
类属性的补充
一: 我们定义的类的属性到底存到哪里了? 有两种方式查看
dir(类名): 查出的是一个名字列表
类名.__dict__: 查出的是一个字典, key 为属性名, value 为属性值
二: 特殊的类属性
类名.__name__# 类的名字 (字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类 (在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组 (在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类 (仅新式类中)
对象的相关知识
class 类名:
def __init__(self, 参数 1, 参数 2):
self. 对象的属性 1 = 参数 1
self. 对象的属性 2 = 参数 2
def 方法名 (self):pass
def 方法名 2(self):pass
对象名 = 类名 (1,2) #对象就是实例, 代表一个具体的东西
- #类名 () : 类名 + 括号就是实例化一个类, 相当于调用了__init__方法
- #括号里传参数, 参数不需要传 self, 其他与 init 中的形参一一对应
- #结果返回一个对象
对象名. 对象的属性 1 #查看对象的属性, 直接用 对象名. 属性名 即可
对象名. 方法名 () #调用类中的方法, 直接用 对象名. 方法名 () 即可
1, 对象查看对象空间所有的属性用__dict__
2, 对象可以对对象的属性进行增删改查 , 方法用万能的.(点)
3, 对象只能对类空间的属性进行查操作
练习一: 在终端输出如下信息
小明, 10 岁, 男, 上山去砍柴
小明, 10 岁, 男, 开车去东北
小明, 10 岁, 男, 最爱大保健
老李, 90 岁, 男, 上山去砍柴
老李, 90 岁, 男, 开车去东北
老李, 90 岁, 男, 最爱大保健
老张...
练习题
类名称空间与对象的名称空间
创建一个类就会创建一个类的名称空间, 用来存储类中定义的所有名字, 这些名字称为类的属性
而类有两种属性: 静态属性和动态属性
静态属性就是直接在类中定义的变量
动态属性就是定义在类中的方法
其中类的数据属性是共享给所有对象的
- >>>id(egg.role)
- 4341594072
- >>>id(Person.role)
- 4341594072
而类的动态属性是绑定到所有对象的
- >>>egg.attack
- <bound method Person.attack of <__main__.Person object at 0x101285860>>
- >>>Person.attack
- <function Person.attack at 0x10127abf8>
创建一个对象 / 实例就会创建一个对象 / 实例的名称空间, 存放对象 / 实例的名字, 称为对象 / 实例的属性
在 obj.name 会先从 obj 自己的名称空间里找 name, 找不到则去类中找, 类也找不到就找父类... 最后都找不到就抛出异常
- class GameRole:
- rule = '游戏规则'
- hp = 1800
- def __init__(self,area,nickname,hp,ad):
- self.area = area
- self.nickname = nickname
- self.hp = hp
- self.ad = ad
- def attack(self):
- print('谁施展了一个攻击')
- def pen(self):
- self.pen=10000
- gailun = GameRole('德玛西呀','草丛伦',1000,75)
- yasuo = GameRole('艾欧尼亚','托儿所',500,150)
- penzi = GameRole('中国','键盘侠',10,100)
- # penzi.pen = 10000
- penzi.pen()
- print(penzi.__dict__)
- # print(gailun.hp)
- # gailun.attack = 666 # 给对象增加一个属性 attack = 666
- # print(gailun.attack)
- gailun.rule = gailun.rule # '游戏规则' ***** 比较难理解
- # gailun.rule = 游戏规则'# 对象. 属性名 ='游戏规则'
- print(gailun.rule)
思路理解
, 对象调用类中的属性与方法是先从自己的空间去找, 没有此属性他会通过类对象指针从类中去找, 类中找不到, 会从父类去找.
, 对象只能查看类中的属性, 不能增删改类中的属性.
, 同一个类实例化出来的对象之间是不能相互访问的, 不同类实例化的对象有可能互相访问.
, 给对象封装属性用__init__, 可以在任意位置.
来源: http://www.bubuko.com/infodetail-2739549.html