一、面向对象初识
1、先了解一下设么是面向对象
之前学习的都是面向过程的程序设计方式, 这种方式的的核心是过程(流水线式思维)
优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向对象的程序设计的核心是对象(上帝式思维),将某些相关的功能(函数)封装到了一起。
优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
2、面向对象的相关名词
类:具有相同特征的一类事物(人、狗、老虎)
对象/实例:类的具体表现,具体的某一个事物(隔壁阿花、楼下旺财)
实例化:类——>对象的过程(这在生活中表现的不明显,我们在后面再慢慢解释)
3、类-->对象-->实例化
结构分析:类一般就分为两部分:变量,方法。
思想分析:创建一个类 公共模板,通过创建个体对象 可以享有公共方法。
定义一个类
class Person: pass
给这个类封装一些属性:
# 封装了两个属性 :必须是人,而且会走
class Person: # 定义一个类 role = 'person' # 人的角色属性都是人 def walk(self): # 人都可以走路,也就是有一个走路方法 print("person is walking...") print(Person.role) # 查看人的role属性 print(Person.walk) # 引用人的走路方法,注意,这里不是在调用
self 约定俗成 self,类中的方法的第一个参数要设定为self,在对象调用方法时,会自动将对象空间传给self。
4、类名调用类中静态属性
class Person: mind = '有思想' animal = '高级动物' language = '文字语言' # 静态属性,静态变量 静态字段 def work(self): # 函数 方法,动态方法,动态属性。 print('人类都会工作') def eat(self): print('人类都需要吃饭') # 方法一:__dict__ 只能查询(不能增删改) 类中所有的静态属性,动态方法。 print(Person.__dict__['mind']) # 有思想 Person.__dict__['mind'] = '无思想的' # 会报错,因为类中的静态属性不可修改 # 方法二: 万能的点 . 可以查,可以改,可增,可删。 print(Person.animal) # 高级动物 Person.animal = '低级动物' # 修改静态属性 print(Person.animal) # 低级动物 Person.name = '有姓名' # 增加一个静态属性name print(Person.name) # 有姓名 del Person.animal # 删除这个静态变量 print(Person.animal) # 会报错,因为此静态变量已被删除
5、类名执行类中的动态方法
一般不建议用类名执行,除非是特殊方法:类方法,静态方法)
class Person: mind = '有思想' animal = '高级动物' language = '文字语言' # 静态属性,静态变量 静态字段 def work(self): # 函数 方法,动态方法,动态属性。 print('人类都会工作') def eat(self): print('人类都需要吃饭') Person.work('大锤') # 类名执行类中的方法,结果为 :人类都会工作
6、实例化对象
实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
实例化对象的过程有几步:
实例化对象在内存中产生一个对象空间(内存地址)。
自动执行 __init__方法并且将对象空间传给了self参数。
在 __init__方法中,给对象空间封装一些静态属性。
class Game_Role: a1 = '英雄联盟' name = '大锤' def __init__(self, name, sex, ad, hp): # __init__方法,特殊方法: 给对象封装属性 self.name = name self.sex = sex self.ad = ad self.hp = hp def work(self): self.hobby = '大刀' print(self.__dict__) gailun = Game_Role('盖伦', 'man', 30, 500) # 实例化一个对象 gailun gailun.work() # {'name': '盖伦', 'sex': 'man', 'ad': 30, 'hp': 500, 'hobby': '大刀'}
7、对象调用类的属性
万能的点: . 可以调用类中的静态属性
class Game_Role: a1 = '英雄联盟' name = '大锤' def __init__(self, name, sex, ad, hp): # __init__方法,特殊方法: 给对象封装属性 self.name = name self.sex = sex self.ad = ad self.hp = hp def work(self): self.hobby = '大刀' print(self.__dict__) gailun = Game_Role('盖伦', 'man', 30, 500) # 实例化一个对象 gailun print(gailun.a1) # 英雄联盟 对象调用类的属性
8、对象执行类中的方法: 对象 . 方法()
class Game_Role: a1 = '英雄联盟' name = '太白' def __init__(self, name, sex, ad, hp): # __init__方法,特殊方法: 给对象封装属性 self.name = name self.sex = sex self.ad = ad self.hp = hp def work(self): self.hobby = '大刀' print(self.__dict__) gailun = Game_Role('盖伦', 'man', 30, 500) # 实例化一个对象 gailun gailun.work() # {'name': '盖伦', 'sex': 'man', 'ad': 30, 'hp': 500, 'hobby': '大刀'}
9、工作中的使用
工作中:类中的静态属性一般通过类名去调用或者改变;
类中的动态方法一般通过对象去执行。
class Game_Role: a1 = '英雄联盟' name = '大锤' def __init__(self, name, sex, ad, hp): self.name = name self.sex = sex self.ad = ad self.hp = hp def work(self): self.hobby = '大刀' print(self.__dict__) gailun = Game_Role('盖伦', 'man', 30, 500) print(Game_Role.name) # 调用类中的静态属性用类名调用 gailun.work() # 调用类中的动态方法用 对象名调用
10、对象查看自己空间的属性
class Game_Role: a1 = '英雄联盟' name = '大锤' def __init__(self, name, sex, ad, hp): self.name = name self.sex = sex self.ad = ad self.hp = hp def work(self): self.hobby = '大刀' print(self.__dict__) gailun = Game_Role('盖伦', 'man', 30, 500) # 查看全部对象gailun查看自己空间的全部属性:__dict__ print(gailun.__dict__) # 查看某个对象自己的静态属性: 万能的. 增删改查。 print(gailun.name) # 查看静态变量name的属性 print(gailun.sex) # 查看封装好的属性
二、组合
组合:就是给一个类封装一个属性,这个属性是另一个类的对象
class Game_Role: # 创建一个游戏人物角色类 area = '召唤师峡谷' def __init__(self, name, sex, ad, hp): self.name = name self.sex = sex self.ad = ad self.hp = hp def fight(self, role1): role1.hp = role1.hp - self.ad # 下行结果为: 盖伦 攻击 狗头, 狗头还剩余220 print('%s 攻击 %s, %s还剩余%s' % (self.name, role1.name, role1.name, role1.hp)) def equit_weapon(self, wea): self.wea = wea # 组合: 对象中的属性是另一个类的对象 class Weapon: # 创建一个武器类 def __init__(self, name, ad): # 接收到sword传过来的参数,name='大宝剑',ad=40 self.name = name self.ad = ad def wea_attack(self, role1, role2): role2.hp = role2.hp - self.ad print('%s 利用 %s 攻击 %s, %s还剩余%s' % (role1.name, self.name, role2.name, role2.name, role2.hp)) # 实例化了三个对象:盖伦、狗头、诺克 p1 = Game_Role('盖伦', 'man', 30, 500) p2 = Game_Role('狗头', '公', 50, 250) p3 = Game_Role('诺克', 'man', 50, 350) # 对象调用类中的方法 p1.fight(p2) # 盖伦调用fight方法,将参数狗头传给lore1 sword = Weapon('大宝剑', 40) sword.wea_attack(p1, p2) # 将P1传给wea_attack的role1, P2传给wea_attack的role2 p1.equit_weapon(sword) # 此方法就是给p1对象封装一个属性,属性值是sword对象 print(p1.wea.name) p1.wea.wea_attack(p1, p2) # 通过p1.wea找到sword 然后在sword.wea_attack执行方法