python--初始面向对象:类的相关知识,对象的相关知识

发布时间:2018-04-10 20:41:26编辑:Run阅读(3278)

    引子

    假设你是一个开发人员,现在需要你开发一款叫做

    当然很简单,两个角色,1个人物,1个boss,且人物和boss都有不同的技能,比如人物用觉醒技能秒了boss,掉了xx装备,boss用大招秒了人物,人物死亡,怎么描述这种不同的人物和他们的功能呢

    根据之前掌握的知识点,写出了下面的代码来描述这两个角色

    '''人物角色信息'''
    def character(name, career, hp, ad):
        # name:人物昵称,career:人物职业, hp:人物血量, ad:人物攻击力
        data = {'name':name, 'career':career, 'hp':hp, 'ad':ad}
        return data
    
    '''boss信息'''
    def boss(name,level, hp, ad):
        # name:boss昵称, level:boss级别 hp:boss血量 ad:boss攻击力
        data = {'name':name, 'level':level, 'hp':hp, 'ad':ad}
        return data


    上面两个方法相当于造了两个模子,游戏里的每个人物和每个boss都拥有相同的属性,游戏开始,你根据一个人或一个boss传入的具体信息来塑造一个具体的人或者boss,怎么生成呢?

    # 传入1号boss具体信息
    one_boss = boss('魔龙教主', '主宰boss', 10000, 5000)
    
    # 传入1号人物具体信息
    one_character = character('一刀秒杀', '战士', 99999, 99999)


    两个角色对象生成了,boss和人物还有不同的功能呀,boss放技能打人物,人物放技能打boss,对不对?怎么实现呢?想到了,可以每个功能函数在写一个,想执行哪个功能,直接调用就可以了,对不?

    def awakening(boss):
        print('玩家:{}对{}释放觉醒技'.format(one_character['name'], one_boss['name']))
        if one_character['ad'] - one_boss['hp'] >= 0:
            print('玩家:{}杀死了{},爆出一把主宰之剑'.format(one_character['name'], one_boss['name']))
    
    def dragon_breath(character):
        print('boss:{}对{}释放了龙息'.format(one_boss['name'], one_character['name']))


    整个代码

    '''人物角色信息'''
    def character(name, career, hp, ad):
        # name:人物昵称,career:人物职业, hp:人物血量, ad:人物攻击力
        data = {'name':name, 'career':career, 'hp':hp, 'ad':ad}
        return data
    
    '''boss信息'''
    def boss(name,level, hp, ad):
        # name:boss昵称, level:boss级别 hp:boss血量 ad:boss攻击力
        data = {'name':name, 'level':level, 'hp':hp, 'ad':ad}
        return data
    
    # 传入1号boss具体信息
    one_boss = boss('魔龙教主', '主宰boss', 10000, 5000)
    
    # 传入1号人物具体信息
    one_character = character('一刀秒杀', '战士', 99999, 99999)
    
    def awakening(boss):
        print('玩家:{}对{}释放觉醒技'.format(one_character['name'], one_boss['name']))
        if one_character['ad'] - one_boss['hp'] >= 0:
            print('玩家:{}杀死了{},爆出一把主宰之剑'.format(one_character['name'], one_boss['name']))
    
    def dragon_breath(character):
        print('boss:{}对{}释放了龙息'.format(one_boss['name'], one_character['name']))
    awakening(one_character)
    dragon_breath(one_boss)

    执行结果如下

    玩家:一刀秒杀对魔龙教主释放觉醒技

    玩家:一刀秒杀杀死了魔龙教主,爆出一把主宰之剑

    boss:魔龙教主对一刀秒杀释放了龙息


    但是这样会有一个问题,人物和boss的信息可以互传,很容易搞混了,怎么办?接着该

    '''人物角色信息'''
    def character(name, career, hp, ad):
        # name:人物昵称,career:人物职业, hp:人物血量, ad:人物攻击力
        data = {'name':name, 'career':career, 'hp':hp, 'ad':ad}
        def awakening(boss):
            print('玩家:{}对{}释放觉醒技'.format(one_character['name'], one_boss['name']))
            if one_character['ad'] - one_boss['hp'] >= 0:
                print('玩家:{}杀死了{},爆出一把主宰之剑'.format(one_character['name'], one_boss['name']))
        data['awakening'] = awakening
        return data
    
    '''boss信息'''
    def boss(name,level, hp, ad):
        # name:boss昵称, level:boss级别 hp:boss血量 ad:boss攻击力
        data = {'name':name, 'level':level, 'hp':hp, 'ad':ad}
        def dragon_breath(character):
            print('boss:{}对{}释放了龙息'.format(one_boss['name'], one_character['name']))
        data['dragon_breath'] = dragon_breath
        return data
    
    # 传入1号boss具体信息
    one_boss = boss('魔龙教主', '主宰boss', 10000, 5000)
    
    # 传入1号人物具体信息
    one_character = character('一刀秒杀', '战士', 99999, 99999)
    
    # 1号人物使用觉醒技攻击(1号boss)
    one_character['awakening'](one_boss)

    执行结果

    玩家:一刀秒杀对魔龙教主释放觉醒技

    玩家:一刀秒杀杀死了魔龙教主,爆出一把主宰之剑


    把人物信息和人物技能放到一个函数里面,boss信息和boss技能放到一个函数里面,防止混用,其实就是简单的面向对象编程,归类!


    面向过程VS面向对象

    面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面对过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西

    有点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可

    缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身

    应用场景:一旦完成基本很少改变的场景,著名的列子有Linux内核,git,以及apache http server等


    面向对象的程序设计的核心是对象(上帝式思维),要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。

    面向对象的程序设计

    优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏一个人物参数的特征和技能修改都很容易。

    缺点:可控性差,无法向面向过程的程序设计流水式的可以很精准的预测问题的处理流程和结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人物的参数的修改极有可能影响一个游戏的平衡

    应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方


    在python中面向对象的程序设计并不是全部

    面向对象变成可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率,另外,基于面向对象的程序可以使他人更加容易理解你的代码逻辑,从而使团队开发变得更从容

    了解一些名词:类,对象,实例,实例化

    类:具有相同特征的一类事物

    对象/实例:具体的某一个事物(隔壁班班花,楼下少妇)

    实例化:类---->对象的过程(这在生活中表现的不明显,后面会在慢慢解释)


    初始类和对象

    python中一切皆为对象,类型的本质就是类。

    在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是‘类’,对象则是这一类事物中具体的一个。

    使用面向对象,首写字母是大写(标准写法,规范写法)

    class Person:
        静态变量 = 123
    print(Person.__dict__)  #内置的双下方法,查看静态变量

    执行结果

    {'__doc__': None, '__module__': '__main__', '__dict__':


    访问静态变量

    class Person:
        静态变量 = 123
    print(Person.__dict__['静态变量'])  # 访问静态变量

    执行结果

    123


    查看静态变量的第一种方式

    class Person:
        静态变量 = 123
    print(Person.__dict__)  # 内置的双下方法
    print(Person.__dict__['静态变量'])  # 内置方法__dict__只能访问静态变量
    Person.__dict__['静态变量'] = 456   # 使用内置__dict__['']方法修改静态变量
    print(Person.__dict__['静态变量'])  # 执行报错,内置方法__dict__只能访问静态变量,不能修改

    执行结果

    {'__weakref__':

    Traceback (most recent call last):

      File "D:/python11_quanzhan/day16/lianxi.py", line 108, in

    123

        Person.__dict__['静态变量'] = 456

    TypeError: 'mappingproxy' object does not support item assignment


    查看静态变量的第二种方式

    class Person:
        静态变量 = 123
    print(Person.静态变量)  # 打印静态变量 
    Person.静态变量 = 456  # 修改静态变量
    print(Person.静态变量)  # 打印修改后的静态变量

    执行结果

    123

    456


    删除静态变量的方法

    class Person:
        静态变量 = 123
    del Person.静态变量
    print(Person.__dict__)

    执行结果

    {'__dict__':

    可以看到  静态变量:123已经删除


    类名

        引用静态变量

            1.类名.__dict__['静态变量名'] 可以查看,但是不能删改

            2.类名.静态变量名 直接就可以访问,可以删改

            3.del 类名.静态变量名 删除一个静态变量


    动态变量就是函数

    class Person:
        静态变量 = 123
        role = 'person'
        def func(self):  # 默认带一个参数self,方法,动态属性
            print(1234567)
    print(Person.静态变量)  # 打印静态变量
    Person.func()  # 执行动态属性,也就是执行类里面的func()函数

    执行结果,报错,缺少一个参数

    Traceback (most recent call last):

    123

      File "D:/python11_quanzhan/day16/lianxi.py", line 128, in

        Person.func()  # 执行动态属性,也就是执行类里面的func()函数

    TypeError: func() missing 1 required positional argument: 'self'


    传入一个参数,在执行,代码如下

    class Person:
        静态变量 = 123
        role = 'person'
        def func(self):  # 默认带一个参数self,方法,动态属性
            print(1234567)
    print(Person.静态变量)  # 打印静态变量
    Person.func(1)  # 执行动态属性,也就是执行类里面的func()函数,传入一个参数1(实参)

    执行结果

    123

    1234567

    Why?为什么传一个参数,就可以执行了?

    引用动态变量

    1 类名.方法名 查看这个方法的内存地址

    2 类名.方法名(实参) 调用了这个方法,必须传一个实参,这个实参传给了self

    只要是类的方法,必须要传self。self的名字(虽然可以改,但是不建议),是一种标准写法,约定俗成


    调用类名加括号,创造一个对象

    创造一个命名空间,唯一属于对象

    st = Person()  # 创造一个对象

    st是对象

    Person是类

    对象=类名()

    类变成对象的过程,是实例化的过程

    blob.png

    实例化,是产生实例的过程

    创造一个对象-实例化

    产生一个实例(对象)的过程

    对象=类名()

    st = Person()

    实例化的过程

    1 创造一个实例,将会作为一个实际参数

    2 自动触发一个__init__的方法,并且把实例以参数的形式传递给__init__方法中的self形参

    3 执行完__init__方法之后,会将self自动返回给st

    class Person:
        role = 'person'  # 静态属性
    
        def __init__(self):  # 动态属性 方法(函数) 默认带一个参数self
            print('执行了!')
            print(self)
            
    st = Person()
    print(st)

    执行结果

    执行了!

    内存地址是一样的

    init里面,不能加return


    例2

    class Person:
        role = 'person'  # 静态属性
    
        def __init__(self, name):
            print('执行我了!')
            print(self, name)
    st = Person('st_sb')
    print(st)

    执行结果,name和self是没有关系的

    执行我了!


    self默认是一个空字典

    class Person:
        role = 'person'  # 静态属性
    
        def __init__(self):
            print(self.__dict__)  # 打印self
    st = Person()

    执行结果

    {}


    类和外部唯一的联系,就是self

    blob.png

    这样,st就拥有自己的字典

    class Person:
        def __init__(self,name,sex,hp,ad):
            self.name = name
            self.sex = sex
            self.hp = hp
            self.ad = ad
    
    
    st = Person('st_sb','人妖',1,5)
    print(st.__dict__)

    执行结果

    {'name': 'st_sb', 'hp': 1, 'ad': 5, 'sex': '人妖'}


    例2

    class Person:
        def __init__(self,name,sex,hp,ad):
            self.name = name
            self.sex = sex
            self.hp = hp
            self.ad = ad
    
    
    st = Person('st_sb','人妖',1,5)
    boss = Person('深渊领主','不详',9999,9999)
    print(st.__dict__)
    print(boss.__dict__)

    执行结果

    {'name': 'st_sb', 'ad': 5, 'sex': '人妖', 'hp': 1}

    {'name': '深渊领主', 'ad': 9999, 'sex': '不详', 'hp': 9999}

    每次调用Person()都会产生一个新的内存空间

    空间会返回给调用者

    blob.png

    类里面的方法,没有顺序之分,一般吧init放到第一个,在类里面的def一般叫方法

    class Person:
        def __init__(self,name,sex,hp,ad):
            self.name = name
            self.sex = sex
            self.hp = hp
            self.ad = ad
    
        def attack(self):
            print('{}发起了一次攻击'.format(self.name))
    st = Person('st_sb', '不详',99,99)
    Person.attack(st)  # 有一个简写
    st.attack()
    boss = Person('深渊领主','不详',9999,9999)
    Person.attack(boss)  # 简写
    boss.attack()

    执行结果

    st_sb发起了一次攻击

    st_sb发起了一次攻击

    深渊领主发起了一次攻击

    深渊领主发起了一次攻击

    方法的调用:(推荐使用第二种)

    类名.方法名(对象名)  # 那么方法中的self参数就指向这个对象

    对象名.方法名()      # 这样写,相当于 方法中的self参数直接指向这个对象

    attack是和Person关联起来的,所以外部可以直接调用attack方法


    小结

    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   #查看对象的属性,直接用 对象名.属性名 即可

    对象名.方法名()     #调用类中的方法,直接用 对象名.方法名() 即可


    练习题:(使用类的方式)

    练习一:在终端输出如下信息

    小明,10岁,男,上山去砍柴

    小明,10岁,男,开车去东北

    小明,10岁,男,最爱大保健

    老李,90岁,男,上山去砍柴

    老李,90岁,男,开车去东北

    老李,90岁,男,最爱大保健

    老张......

    class Info(object):
        def __init__(self, name, age, sex='男', content=('上山去砍柴', '开车去东北', '最爱大保健')):
            self.name = name
            self.age = age
            self.sex = sex
            self.content = content
    
        def run(self):
            for i in self.content:
                print('{},{},{},{}'.format(self.name, self.age, self.sex, i))
    
    
    st = Info('小明', '10岁')
    xt = Info('老李', '90岁')
    st.run()
    xt.run()

    执行结果

    小明,10岁,男,上山去砍柴

    小明,10岁,男,开车去东北

    小明,10岁,男,最爱大保健

    老李,90岁,男,上山去砍柴

    老李,90岁,男,开车去东北

    老李,90岁,男,最爱大保健


关键字