面向对象基础、类和对象、绑定方法
一、面向对象编程
回顾:面向过程编程
是一种之前程序员们设计出来的比较好的编程方法,也是一种编程思想。
核心是过程二字,顾名思义,就是先干什么,再干什么,完成一个事情具有的所有步骤。
优点:复杂的流程简单化,程序化,一步一步拆分,降低开发难度。
缺点:扩展性差, 不容易维护。
主要使用的场景:对扩展性要求不高的,如Linux内核,shell脚本
何为面向对象?
核心是‘对象’二字。
与面向过程机械式的思维方式形成鲜明对比,面向对象更加注重对现实世界而非流程的模拟,是一种“上帝式”的思维方式。
优点:
1.对于指挥者(程序员)来说,不需要再关心具体步骤
2.扩展性,一个单独的个体的特征或行为发生变化时 不会影响到别人
缺点:
1.程序的复杂度变高,你得需要设计这些对象,注意要避免过度设计得问题
2.程序得执行结果可控性低
二、类和对象
什么是对象:
在现实生活中实实在在存在的,具备自己的特征和行为的事物
反过来说 对象就是 特征和行为(技能)的结合体
什么是类
一堆具备相同特征和行为的事物的抽象概念,不实际存在。
conclusion:
先有类还是先有对象:
生活中:
生活中类怎么来的,是通过对象的特征和行为抽取而来,
所以是先有对象才有了类
编程中:
必须是先有类 才能有对象,因为你必须先告诉程序,你这个对象有什么样的特征和行为
类的作用:用于描述该类的对象具备什么样的特征和行为
补充说明:
站的角度不同,定义出的类是截然不同的;
现实中的类并不完全等于程序中的类,比如现实中的公司类,在程序中有时需要拆分成部门类,业务类等;
有时为了编程需求,程序中也可能会定义现实中不存在的类,比如策略类,现实中并不存在,但是在程序中却是一个很常见的类
三、Python中类和对象的操作
class Student: # 如果每个对象的这个属性都相同 才应该定义到类中 比如所有人的学校都相同 school = "北京大学"
# 创建对象 # 语法: 在类名后加括号 与调用函数写法相同 # stu = Student() # # 访问对象的属性 # print(stu.school) # print(Student.school)
# 修改属性的值 # stu.school = "清华大学" # print(stu.school) # # # 增加属性 # stu.room_num = "1008" # print(stu.room_num) # # # 删除属性 # del stu.room_num # print(stu.room_num)
# 对象 与类的名称空间是独立的 # stu.school = "深圳大学" # 为对象的属性赋予新的值 # print(Student.school) # 类中的属性不会变化 # stu.room_num = "1008" # 为对象增加属性 # # print(Student.room_num) #类中也不会出现新的属性 # print(stu.__dict__) # print(Student.__dict__)
对象的属性查找顺序:
对象自己的名称空间 -> 类的名称空间
四、__init__方法详解
该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值。
__init__称之为初始化函数 它会在创建对象的时候自动执行
创建对象时
1.创建一个空对象
2.执行__init__函数 并且自动传入了这个对象
该函数的作用,就是为对象的属性赋初始值
def __init__(self,name,color,age,gender): print("狗__init__执行了") print(self) self.name = name self.age = age self.color = color self.gender = gender
# 在创建对象时,传入参数 dog1 = Dog("大黄","黄色",2,"female") dog2 = Dog("二哈","白色",2,"female") print(dog1.__dict__) print(dog2.__dict__)
注意:
1. 使用场景 需要为每个对象定制不同的属性值
2.__init__在创建对象后自动执行
3.第一个self参数 指的是这个对象本身 不需要手动传值
五、绑定方法
class Person: country = "China" def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def sleep(self): print("sleeping")def eat(self): print("eating")
# p1 = Person("矮根",68,"female") # p2 = Person("成伟",18,"female") # 类调用类中函数 与 对象调用的区别 # p1.sleep() # p2.sleep() # print(Person.sleep) # print(p1.sleep) # 类调用 # Person.sleep(10) # 对象调用 # p1.sleep()
类调用与对象调用的区别
对于类而言 sleep就是一个普通函数
对对象而言 sleep是一个绑定方法
绑定方法是什么?
是对象与类中的某个函数的绑定关系 就像生活中 我们都会吃饭 我吃饭你不会饱
那么吃饭就是我自己的绑定方法
为什么要把函数进行绑定?
因为对象的行为 通常都需要访问这个对象的数据 或是修改这个对象的数据
如果没有对象 直接调用函数是没有意义的 在函数中访问不到对象的数据
所以将对象和函数进行绑定
特殊之处
在使用绑定方法时 不需要关心self参数 会自动将这个对象本身传进来
对象调用绑定方法时 最后执行的还是类中的那个函数
练习题:
模拟一个王者荣耀对砍游戏,两个英雄可以对砍 如果血量小于等于0 就GG,考虑所需的对象和英雄的对象。
class Hero: def __init__(self,hero_type,name,blood,q,w,e): self.hero_type = hero_type self.blood = blood self.name = name self.q = q self.w = w self.e = e def Q(self,enemy):# 跳起来给你一刀 print('%s 对 %s 释放了Q技能 造成%s点伤害,对方剩余血量%s' %(self.name,enemy.name,self.q,enemy.blood-self.q)) enemy.blood -=self.q if enemy.blood <= 0 : print('Hero %s is GG'%enemy.name) def W(self,enemy):# 给你一脚 print('%s 对 %s 释放了W技能 造成%s点伤害,对方剩余血量%s' %(self.name,enemy.name,self.w,enemy.blood-self.w)) enemy.blood -=self.w if enemy.blood <= 0 : print('Hero %s is GG'%enemy.name) def E(self,enemy):# 大宝剑 print('%s 对 %s 释放了Q技能 造成%s点伤害,对方剩余血量%s' %(self.name,enemy.name,self.e,enemy.blood-self.e)) enemy.blood -= self.e if enemy.blood <= 0 : print('Hero %s is GG'%enemy.name) # 定义英雄的对象 yashe = Hero('战士','亚瑟',200,50,30,100) #q,w,e 50,30,100 daji = Hero('法师','妲己',180,10,30,180) #q,w,e 10,30,180 yashe.E(daji) daji.W(yashe) yashe.W(daji) daji.Q(yashe) yashe.Q(daji)
输出:
亚瑟 对 妲己 释放了Q技能 造成100点伤害,对方剩余血量80 妲己 对 亚瑟 释放了W技能 造成30点伤害,对方剩余血量170 亚瑟 对 妲己 释放了W技能 造成30点伤害,对方剩余血量50 妲己 对 亚瑟 释放了Q技能 造成10点伤害,对方剩余血量160 亚瑟 对 妲己 释放了Q技能 造成50点伤害,对方剩余血量0 Hero 妲己 is GG