面向对象编程思想:OOP | 类和对象知识

今日内容:


 

面向对象编程思想:OOP


 

什么是面向对象?

  • 面向对象是一种编程思想,是前辈们,总结的经验,指导程序员如何编写出更好的程序
  • 核心是对象,程序就是一系列对象的集合,程序员负责调度控制这些对象来交互着完成任务

案例: 1-把大象装进冰箱

  • 面向过程:
    • 1.打开冰箱
    • 2.装入大象
    • 3.关闭冰箱
  • 面向对象:
    • 找个具备装大象的技能的对象
    • 在面向对象中,程序员的角度发生改变,从具体的操作者变成了指挥者
注意: 对象不是凭空产生的,需要我们自己设计

案例: 2-西天取经

  • 如来有一堆破书要传出来,他没有自己干,而是找了五个对象帮他去干
  • 如来只要负责控制调度的对象即可
  • 如果某个对象发生变化,也不会影响其他的对象,扩展性与灵活性强

案例: 3-曹操吟诗

  • 需求1:喝酒吃肉,人生真爽
  • 需求2:喝酒吃肉,人生几何
  • 需求3:对酒当歌,人生几何

这种一直改需求的情况,将字拆成一个一个的,要用时拼起来就行

面向对象的三大优点:

  • 1.扩展性
  • 2.灵活性
  • 3.重用性

面向对象的缺点:

  • 1.程序的复杂度提高
  • 2.无法准确预知结果

使用场景:

  • 对扩展性要求较高的程序,通常是直接面向用户的,例如QQ与微信

注意点: 不是所有程序都要面向对象,得分析具体需求

面向过程编程思想:


 

关键的核心是过程,过程就是一步一步的执行步骤

 

面向过程优缺点:

  • 优点: 逻辑清晰,复杂问题简单化,流程化
  • 缺点: 扩展性差,可维护性差

使用场景:

  • 对扩展性要求较低的程序

例如: 系统内核,git,计算器

类和对象:


 

下面是OOP中的最核心的两个概念:

  • 类:

    • 即类型,类别,是一种抽象概念
    • 是一系列具备相同特征和行为的对象的集合
  • 对象:

    • 就是具体存在的某个事物,具备自己的特征与行为
    • 对象就是特征和技能的结合体

类和对象的关系:

  • 类包含一系列对象
  • 对象属于某个类
  • 在生活中是先有对象再有类
  • 而在程序中是先有类才能有对象,我们必须先告诉计算机这类的对象有什么特征,有什么行为

总结一个结论:

  • 在使用面向对象编程时,第一步就是思考需要什么样的对象,对象具备什么样的特征和行为,从而根据这信息总结出需要的类型

 

创建类和对象:


 

定义类的语法:

class 类的名称:

    # 类中的内容 描述属性和技能

    # 描述属性用变量

    # 描述行为用函数

   
# 类名称的书写规范: 首先是见名知意,名称是大驼峰命名法

# 驼峰就是单词首字母大写,大驼峰是第一个字母大写,小驼峰是第一个字母小写

类的定义:

class Student:

    pass# 创建对象的语法,调用类,即类名加括号

stu = Student()

print(stu)  # <__main__.Student object at 内存地址>

print(Student)  # <class'__main__.Studet'>

创建对象的语法:

class Person:

    pass# 创建对象
p = Person()

属性的写法:

  • 属性可以写在类中类中的属性,是所有对象公共的
  • 也可以写在对象中
  • 对象中的数,每个对象独特的(不一样的)
  • 如果类中和对象中存在同样的属性,先访问对象,如果没有,再访问类

练习: 描述一个老师类,需要包含一个公共属性和一个独特的属性

class Teacher:

    school = 'oldboy'


t1 = Teacher()

t1.name = 'jack'

t1.age = 18

​
t2 = Teacher()

t2.name = 'nick'

t2.age = 28

属性的增删查改:

# 增加属性
# 对象变量名称.属性名称 = 属性值
# 删除属性
# del 对象的变量名称.属性名称
# 修改属性
# 对象.属性 = 新的值
# 查看属性(访问的是对象的所有属性)
print(对象.__dict__)
​
# __doc__是类的注释
print(对象.__class__)  # 访问对象的类信息

实例:

class Person1:

    name = '朱质健'

    age = 88

    sex = 'male'

   
p1 = Person1()

print(p1.name)  # 朱质健

​
p2 = Person1()

print(p2.name)  # 朱质健
​
​
class Person2:

    desc = '都能吃饭'

​
p3 = Person2()

p3.name = 'bilibili'

​
p4 = Person2()

p4.name = 'bangbangbang'print(p3.name)  # bilibili

print(p4.name)  # bangbangbang

初始化对象的属性:

class Teacher:

    school = 'oldboy'

    
t1 = Teacher()

t2 = Teacher()

​
init(t1,'jason',20)

init(t2,'tank',20)
​
​
class Teacher:

    school = 'oldboy'

    
    def init(obj,name,age):

        obj.name = name

        obj.age = age

        
    def __init__(self,name,age)

        self.name = name

        self.age = age

​
t1 = Teacher('jason',18)

Teacher.__init__(t1,'jason')

__init__方法:


 

它叫做初始化方法,本质上就是一个函数

  • 特点1:
    • 当实例化对象时,会自动执行__init__方法
  • 特点2:
    • 会自动将对象作为第一个参数传入,参数名称为self,self也可以是别的名字,不建议改

功能:

  • 用户给对象赋初始值

练习: 创建一个类,具备几个属性,通过初始化方法来给他设置属性

class Dog:

    def __init__(self,kind,color,age):

        self.kind = kind

        self.color = color

         self.age = age

       
d1 = Dog('二哈','黑白',1)

d2 = Dog('泰迪','棕色',2)

初始化方法不仅仅用于赋值:

class PC:

    def __init__(self,kind,price,sys):

        self.kind = kind

        self.price = price

        self.sys = sys

        # 除了赋值以外的初始化操作,例如:启动BIOS等
        print('启动BIOS')

        print('启动系统分区')

        print('加载系统界面')

        print('启动成功>>>')

        return None  # 这个函数不能有其他返回值,只能是None,规定如此        

为对象定制行为:

class Student:

    school = 'oldgirl'

    def __init__(self,name,age,gender)

        self.name = name

        self.age = age

        self.gender = gender

    
    def study(self):

        print(self)

    
    def say_hi(self):

        print('hello i am a student! my name is %s'%self.name)

​
stu1 = Student('jack',20,'male')

stu2 = Student('rose',18,'female')

​
stu1.say_hi()

stu2.say_hi()

​
Student.say_hi(stu1)  # 等价于stu1.say_hi()

print(type(Student.say_hi))  # <class 'function'>

print(type.stu1.say_hi)  # <class 'method'>

总结:对象的精髓就是将数据和处理数据的函数整合到一起,这样一来,拿到一个对象就同时拿到了需要同时处理数据的函数

对象的绑定方法:


 

默认情况下类中的方法都是对象绑定方法

其特殊之处在于:

  • 当使用对象,调用该函数时会自动传入对象本身,作为第一个参数
  • 当使用类名,来调用时他就是一个普通函数,有几个参数就得传几个参数

练习:写一个学生类,具备一个打招呼的技能,要能输出自己的名字信息

class Student:

    def __init__(self,name):

        self.name = name

    def say_hi(self):

        print('hello my name is $s'%self.name)

类的绑定方法:


 

类绑定方法用@classmethod来装饰

特殊之处:

  • 不管用类还是对象调用,都会自动传入类本身,作为第一个参数

什么时候绑定给对象:

  • 当函数逻辑需要访问对象中的数据时

什么时候绑定给类:

  • 当函数逻辑需要访问类中的数据时
class OldBoyStudent:

    school = 'oldboy'

    def __init__(self,name):

        self.name = name

        
    @classmethod
    def show_school(cls):
print(cls) OldBoyStudent.show_school() # <class'__main__.OldBoyStudent'> print(OldBoyStudent) # <class'__main__.OldBoyStudent'>

非绑定方法:


 

或叫做静态方法,就是既不需要访问类的数据,也不需要访问对象的数据,而且它并不常用

语法:@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)  # rose

对象之间交互练习:


 

需求设计王者荣耀中的英雄类,每个英雄对象可以对其他英雄对象使用技能

具备以下属性:

  • 英雄名称,等级,血量和Q_hurt,W_hurt,E_hurt 三个属性,表示各技能的伤害量

具备以下技能:

  • Q W E
  • 三个技能都需要一个敌方英雄作为参数,当敌方血量小于等于0时角色死亡

代码实现(常规的简单方法):

import random
import time
​
class Hero:

    def __init__(self,name,level,blood,attack,q_hurt,w_hurt,e_hurt)

         # self.name = name
         # self.level = level
         # self.blood = blood
         # self.attack = attack
         # self.q_hurt = q_hurt
         # self.w_hurt = w_hurt
         # self.e_hurt = e_hurt
         
         lcs = locals()

         lcs.pop('self')

         self.__dict__.updated(lcs)

     
    def attack(self,enemy):

        enemy.blood -= self.attack

         print('%s对%s释放了普通攻击,造成了%s伤害,敌人剩余血量%s'%(self.name, enemy.name, self.attack, enemy_blood)

        if enemy.blood <= 0:

            print('%s被%s使用普通攻击击杀了'%(enemy.name,self.name))

            
    def Q(self,enemy):

        enemy.blood -= self.q_hert

         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_hert

         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_hert

         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,200,600,0,50)

h2 = Hero('妲己',20,2000,200,600,0,50)

​
# 常规攻击方式
h1.attack(h2)

h2.Q(h1)

h2.W(h1)

h2.E(h1)

英雄大乱斗(很有趣💗):

import random
import time
​
class Hero:
    def __init__(self,name,level,blood,attack,q_hurt,w_hurt,e_hurt)
         lcs = locals()
         lcs.pop('self')
         self.__dict__.updated(lcs)
​
    def attack(self,enemy):
        enemy.blood -= self.attack
         print('%s对%s释放了普通攻击,造成了%s伤害,敌人剩余血量%s'%(self.name, enemy.name, self.attack, enemy_blood)
        if enemy.blood <= 0:
            print('%s被%s使用普通攻击击杀了'%(enemy.name,self.name))
            
    def Q(self,enemy):
        enemy.blood -= self.q_hert
         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_hert
         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_hert
         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,200,600,0,50)
h2 = Hero('妲己',20,2000,200,600,0,50)
h3 = Hero('鲁班',20,1500,500,200,200,50)
h4 = Hero('蔡文姬',20,2000,100,800,100,100)
               
# 从字典中随机拿出一个值
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)
    fun = 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)

 


       

 

posted @ 2019-07-24 16:43  泡泡茶壶i  阅读(392)  评论(0编辑  收藏  举报