d20 面向对象
Posted komorebi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了d20 面向对象相关的知识,希望对你有一定的参考价值。
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。
是将数据和处理数据的函数绑定到一起封装到对象中
对象是特征与技能的结合体,基于面向对象设计程序
例子: 把大象装进冰箱 ?
面向过程:
1.打开冰箱
2.装入大象
3.关闭冰箱
面向对象:
找个具有装大象的技能的对象
在面向对象中程序员的角度发生改变,从具体的操作者变成了指挥者;
强调:对象不是凭空产生的,需要我们自己设计
优缺点
优点:
1.提高扩展性,当一个对象发生了修改时,对其他对象时没有任何影响的,对象之间相互独立,耦合度变得更低了
2.提高复用性
3.提高灵活性,如果某个对象发生变化,也不会影响其他的对象 , 扩展性
缺点:
1.可控性差,无法预知结果
2.程序的复杂度高
应用场景:
对扩展性要求较高的程序
面向过程编程思想
优点:逻辑清晰,将复杂问题简单化,流程化,
缺点:扩展性差,可维护性差,牵一发而动全身
使用场景:
对扩展性要求较低的程序例如:系统内核,git,计算器
类和对象
类
是一系列具有相同特征和行为的集合体,是一种抽象概念
即类型,类别
对象
具备某种特征与行为的结合体,在程序中用变量来表示对象的特征,函数表示对象的技能,在生活中万物皆对象
对象:将变量与函数结合在一起,形成一个整体
也可以理解为:
变量的作用是存储数据,函数的作用在处理数据
对象是将数据与处理数据的函数绑定在一起
编程思想不是某一个具体语言或技术 ,
面向对象的语言:
python,Java,C++,C#
面向过程:
C,ruby
在python中,定义类通过class关键字:
class Student: pass
class 后面紧跟是类名,遵循python 编码规范,类名通常是大写开头的单词,多个单词时使用驼峰命名法
大驼峰命名法 class Student: pass 小驼峰命名法 class student: pass
class Student: pass #创建对象,通过类名加()实例化产生一个对象 p = Student() print(p) #实例化得到的内存地址 <__main__.Student object at 0x00000000022EC978> print(Student) #得到的类 <class ‘__main__.Student‘>
属性的写法
属性可以写在类中 类中的属性,是所有对象公共的 也可以写在对象中 对象中的属性,是每个对象独特的(不一样的) 如果类中和对象中存在同样的属性,先访问对象 如果没有在访问类 练习: 描述一个老师类 需要包含 一个公共属性和 一个独特的属性 class Teacher: school = "oldboy" t1 = Teacher() t1.name = "jack" t1.age = 28
对象是特征(属性)与行为(方法)的结合体
其添加属性可以在创建对象后使用点语法(变量名加 . )
比如为对象添加name属性
class Student: pass #创建对象,通过类名加()实例化产生一个对象 p = Student() print(p) print(Student) p.name = "Jerry"
同样通过点语法来获取对象的属性值
print(p.name) #输出 Jerry
增加属性 对象变量名称.属性名称 = 属性值 删除属性 del 对象的变量名称.属性名称 修改 对象.属性 = 新的值 查看属性 访问的是对象的所有属性 print(对象.__dict__) 访问对象的类信息 print(对象.__class__) 访问对象的类名 print(对象.__name__)
初始化方法
用于为对象的属性设置初始值的函数
class Student: def __init__ (self,name): print("init run") self.name = name s1 = Student(‘李三‘) s2 = Student(‘王五‘) 注意:该函数不能有任何返回值/.... 只能是None 规定如此..
执行过程:
在创建对象时Student("jack")
会申请新的内存空间用于保存对象数据,接着自动调__init__函数
__init__函数要求第一个参数必须是self,该参数表示需要被初始化的对象本身,这样就可以将name属性绑定到对象上,有了__init__
方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__
方法匹配的参数,但self
不需要传,Python解释器自己会把实例变量传进去:
# p1 = Student() # 以上代码将抛出异常:TypeError: __init__() missing 1 required positional argument: ‘name‘ p1 = Student("jack") # 输出 init run print(p1.name) # 输出 jack
总结: - init函数用于为对象属性设置初始值 - 在创建对象时会自动调用 - 自动传入对象本身
属性查找顺序
可以将类中的内容都称之为属性,变量称为数据属性,函数就叫函数属性
类中可以声明变量来表示数据属性,为Student
类添加数据属性和函数属性
class Student: school = "Tsinghua" #数据属性 def say_hello(self):#函数属性 print("hello i am a student") def __init__ (self,name): #初始化函数 self.name = name
也可以使用点语法在创建对象后为对象增加数据属性
stu = Student("Maria") stu.age = 20
创建对象后为增加的数据属性,是这个对象特有的,去其他对象没有关联
查找顺序:
优先查找对象自己的名称空间,如果没有则在类中找,如果类中也没有则到父类中找,直到找到为止,如果父类中也没有则抛出异常
class Student: school = ‘beidaokou‘ def __init__(self,name): self.name = name stu1 = Student("Jack") stu2 = Student("Rose") #1.类中的数据属性是所有对象共享的 print(stu1.school) print(stu2.school) #输出均为 beidaokou #2.类中的数据属性访问的是同一块内存 print(id(stu1.school)) print(id(stu2.school)) #输出 4470412656 #输出 4470412656 #3.类的函数属性是绑定给对象使用的,bound method称为绑定方法,每个对象的绑定方法内存地址不一样 print(stu1.say_hello) print(stu2.say_hello) #输出 <bound method Student.say_hello of <__main__.Student object at 0x10cc405f8>> #输出 <bound method Student.say_hello of <__main__.Student object at 0x10cc40630>> #4.优先访问对象自己的名称空间 # 修改stu1的学习属性为北京大学 会在自stu1的名称空间增加school属性 stu1.school = "Beijing" print(stu1.__dict__) print(stu2.__dict__) #输出 ‘name‘: ‘Jack‘, ‘school‘: ‘Beijing‘ #输出 ‘name‘: ‘Rose‘ #4.1再次查看学校属性 print(stu1.school) print(stu2.school) #输出 Beijing #输出 Tsinghua #__dict__用于访问对象的名称空间 本质是一个字典类型数据,存储名称与值的映射关系
绑定方法
1.绑定到对象的方法:没有被任何装饰器装饰的方法。
在类中定义的函数默认都是绑定到对象的方法
特点:参数的第一个必须是self 表示当前对象本身,使用对象来调用,调用时会自动传入对象
class Student: def __init__(self,name): self.name = name def say_hi(self): print("hello my name is %s" % self.name)
2.绑定到类的方法:用classmethod装饰器装饰的方法。
特点:参数的第一个必须是cls表示当前类本身,使用类名来调用,调用时会自动传入类
class OldBoyStudent: school = "oldboy" def __init__(self,name): self.name = name @classmethod def show_school(cls): # print(self.school) print(cls)
什么时候绑定给对象:当函数逻辑需要访问对象中的数据时
什么时候绑定给类:当函数逻辑需要访问类中的数据时
用staticmethod装饰器装饰的方法
不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通函数
不过由于作用域在类中所以需要使用类或对象类调用
class OldBoyStudent: school = "oldboy" def __init__(self,name): self.name = name @staticmethod def print_hello(): print("hello world")
练习:为学生类添加一个save方法 一个get方法
save是将对象存储到文件中
get是从文件中获取对象
import pickle class Student: def __init__(self,name): self.name = name def say_hi(self): print("name:",self.name) def save(self): with open(self.name,"wb") as f: pickle.dump(self,f) @staticmethod def get(name): with open(name,"rb") as f: obj = pickle.load(f) return obj # stu = Student("rose") # stu.save() # # # stu1 = Student("jack") # stu1.save() # obj = Student.get("rose") # print(obj.name) # # obj = Student.get("jack") # print(obj.name) print(Student.__name__)
需求设计王者荣耀中的英雄类,每个英雄对象可以对其他英雄对象使用技能
具备以下属性
英雄名称,等级,血量
和Q_hurt,W_hurt,E_hurt 三个属性,表示各技能的伤害量
具备以下技能
Q W E
三个技能都需要一个敌方英雄作为参数,当敌方血量小于等于0时角色死亡
import random import time class Hero: def __init__(self,name,level,blood,att,q_hurt,w_hurt,e_hurt): # 简便写法 lcs = locals() lcs.pop("self") self.__dict__.update(lcs) def attack(self,enemy): enemy.blood -= self.att print("%s对%s释放了普通攻击 造成了%s的伤害 敌人剩余血量%s" % (self.name, enemy.name, self.att, enemy.blood)) if enemy.blood <= 0: print("%s被%s使用普通攻击击杀了" % (enemy.name,self.name)) def Q(self,enemy): enemy.blood -= self.q_hurt print("%s对%s释放了Q 造成了%s的伤害 敌人剩余血量%s" % (self.name, enemy.name, self.q_hurt, enemy.blood)) if enemy.blood <= 0: print("%s被%s使用Q技能击杀了" % (enemy.name, self.name)) def W(self,enemy): enemy.blood -= self.w_hurt print("%s对%s释放了W 造成了%s的伤害 敌人剩余血量%s" % (self.name, enemy.name, self.w_hurt, enemy.blood)) if enemy.blood <= 0: print("%s被%s使用W技能击杀了" % (enemy.name, self.name)) def E(self,enemy): enemy.blood -= self.e_hurt print("%s对%s释放了E 造成了%s的伤害 敌人剩余血量%s" % (self.name,enemy.name,self.e_hurt,enemy.blood)) if enemy.blood <= 0: print("%s被%s使用E技能击杀了" % (enemy.name, self.name)) h1 = Hero("亚索",20,2000,100,600,0,1000) h2 = Hero("妲己",20,2000,100,600,500,1000) h3 = Hero("鲁班",20,1500,700,100,200,300) h4 = Hero("蔡文姬",20,2000,10,0,0,10) # # h1.attack(h2) # h2.Q(h1) # h2.E(h1) # h2.W(h1) #从字典中随机拿出一个值 def random_hero(heros): hero_index = random.randint(1, len(heros)) return heros[hero_index] while True: # # 把所有的攻击方法装到字典里 为了随机取出一个 funcs = 1: Hero.Q, 2: Hero.W, 3: Hero.E, 4: Hero.attack func_index = random.randint(1, 4) func = funcs[func_index] # 把所有的英雄方法装到字典里 为了随机取出一个 heros = 1: h1, 2: h2, 3: h3, 4: h4 hero = random_hero(heros) # 剩余的英雄们 other_heros = new_index = 1 for k, v in heros.items(): if v != hero: other_heros[new_index] = v new_index += 1 # 从剩余的英雄中随机挑出一个英雄来挨打 enemy = random_hero(other_heros) # 打他 func(hero, enemy) if enemy.blood <= 0: break time.sleep(0.5)
以上是关于d20 面向对象的主要内容,如果未能解决你的问题,请参考以下文章