python3--对象之间的交互,类命名空间与对象、实例的命令空间

发布时间:2018-04-11 16:59:09编辑:Run阅读(3915)

    对象之间的交互

    现在有个游戏人与狗,人定义一个类,狗定义一个类,如何让两个类之间互相交互起来,让这个游戏变得更加有意思,代码如下

    #!/usr/bin/env python
    # coding: utf-8
    __author__ = 'www.py3study.com'
    class Person:  # 定义一个人类
        role = 'person'  # 人的角色属性都是人
        def __init__(self, name, sex, hp, ad):
            self.name = name  # 每个角色都有自己的昵称
            self.sex = sex   # 性别
            self.hp = hp  # 血量
            self.ad = ad  # 攻击力
    
        def attack(self, dog):
            # 人可以攻击狗,这里的dog也是一个对象
            # 人攻击狗,那么狗的生命值会根据人的攻击力而下降
            dog.hp -= self.ad
            print('{}攻击了{},{}掉了{}点血'.format(self.name,dog.name,dog.name,self.ad))
    
    class Dog:  # 定义狗类
        role = 'dog'
        def __init__(self, name, breed, hp, ad):
            self.name = name  # 每一只狗都有自己的昵称
            self.breed = breed  # 狗品种
            self.hp = hp  # 狗的血量
            self.ad = ad  # 狗的攻击力
    
        def bite(self, people):
            # 狗可以咬人,这里的狗也是一个对象
            # 狗咬人,那么人的生命值就会根据狗的攻击力下降
            people.hp -= self.ad
            print('{}攻击了{},{}掉了{}点血'.format(self.name, people.name, people.name, self.ad))
    
    boss_sam = Person('Sam', '男', 100, 100)  # 实例化一个角色boss_sam
    ha2 = Dog('二愣子', '哈士奇', 50, 50)     # 实例化一个角色ha2
    boss_sam.attack(ha2)  # boss_sam攻击了ha2, 
    print(ha2.hp)         # 打印ha2的血量
    ha2.bite(boss_sam)    # ha2咬了boss_sam
    print(boss_sam.hp)    # 打印boss_sam的血量

    执行结果

    Sam攻击了二愣子,二愣子掉了100点血

    -50

    二愣子攻击了Sam,Sam掉了50点血

    50


    例2

    from math import pi
    class Circle:  # Circle类名
        '''
        定义了一个圆形类;
        提供计算面积(area)和周长(perimeter)的方法
        圆的面积为:圆周率×2×半径
        圆的周长为:圆周率×半径的平方
        '''
        def __init__(self, radius):  # radius半径
            self.radius = radius
    
        def perimeter(self):
            return pi * self.radius * 2
    
        def area(self):
            return pi * self.radius ** 2
    
    circle = Circle(10)  # 实例化一个圆,传入半径值10
    areal = circle.area()  # 计算圆面积
    perl = circle.perimeter()  # 计算圆周长
    print('半径为10的圆面积是:{},周长是{}'.format(areal,perl))

    执行结果

    半径为10的圆面积是:314.1592653589793,周长是62.83185307179586


    例3,上面题目的升级版,计算半径分别是1,3,5,7,9圆的面积与周长

    from math import pi
    class Circle:  # Circle类名
        '''
        定义了一个圆形类;
        提供计算面积(area)和周长(perimeter)的方法
        圆的面积为:圆周率×2×半径
        圆的周长为:圆周率×半径的平方
        '''
        def __init__(self, radius):  # radius半径
            self.radius = radius
    
        def perimeter(self):
            return pi * self.radius * 2
    
        def area(self):
            return pi * self.radius ** 2
    
    for i in range(1,10,2):  # 步长为2,i的值为1,3,5,7,9
        cl = Circle(i)  # 实例化参入变量i,i为半径1,3,5,7,9
        print(cl.perimeter())  # 打印圆周长
        print(cl.area())  # 打印圆面积

    执行结果

    6.283185307179586

    3.141592653589793

    18.84955592153876

    28.274333882308138

    31.41592653589793

    78.53981633974483

    43.982297150257104

    153.93804002589985

    56.548667764616276

    254.46900494077323


    类命名空间与对象、实例的命名空间

    创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这里名字称为类的属性

    而类有两种属性:静态属性和动态属性

    1 静态属性就是直接在类中定义的变量

    2 动态属性就是定义在类中的方法

    例1,错误的示例

    class Person:
        role = 'person'
        def __init__(self, name, sex, hp, ad):
            self.name = name
            self.sex = sex
            self.hp = hp
            self.ad = ad
            self.attack = 'hahaha哦了'
    
        def attack(self):
            print('{}发起了一次攻击'.format(self.name))
    
    sam = Person('sam_sb', '不详', 9999, 9999)
    sam.attack()
    print(sam.__dict__)

    执行报错

    TypeError: 'str' object is not callable

    为什么呢?因为attack变成字符串了,它不能执行

    blob.png

    改成

    print(sam.attack)

    print(sam.__dict__)

    执行结果

    hahaha哦了

    {'sex': '不详', 'ad': 9999, 'name': '高富帅', 'hp': 9999, 'attack': 'hahaha哦了'}


    类的数据属性是共享给所有对象的,根据上面的例子,在添加一个实例对象

    class Person:
        role = 'person'
        def __init__(self, name, sex, hp, ad):
            self.name = name
            self.sex = sex
            self.hp = hp
            self.ad = ad
            self.attack = 'hahaha哦了'
    
        def attack(self):
            print('{}发起了一次攻击'.format(self.name))
    
    sam = Person('白人', '不详', 9999, 9999)
    tom = Person('黑人', '不详', 1, 1)
    print(sam.role)
    print(tom.role)

    执行结果

    person

    person


    修改类变量

    class Person:
        role = 'person'
        def __init__(self, name, sex, hp, ad):
            self.name = name
            self.sex = sex
            self.hp = hp
            self.ad = ad
            self.attack = 'hahaha哦了'
    
        def attack(self):
            print('{}发起了一次攻击'.format(self.name))
    
    sam = Person('白人', '不详', 9999, 9999)
    tom = Person('黑人', '不详', 1, 1)
    sam.role = 'hahaha'
    print(sam.role)
    print(tom.role)

    执行结果

    hahaha

    person

    但凡是对象操作类属性,它是没有权利的,它只能存储在自己内存空间里面,类可以没有init方法


    模拟人生游戏,模拟一家人赚钱的游戏

    例,错误示例

    class Person:
        money = 0
        def __init__(self, name):
            self.name = name
        def work(self):
            print(self.name, '工作,赚了1000块')
            self.money += 1000
    
    father = Person('father')
    mother = Person('motner')
    father.work()
    mother.work()
    print(Person.money)

    执行结果

    father 工作,赚了1000块

    motner 工作,赚了1000块

    0


    但是钱没有涨?为什么?

    每一次重新赋值,相当于一个新的变量

    加法运算时,拿了类变量,对于类变量,mong=0,它还是0

    怎么解决这个问题呢?

    例2

    class Person:
        money = 0
        def __init__(self, name):
            self.name = name
        def work(self):
            print(self.name, '工作,赚了1000块')
            Person.money += 1000
    
    father = Person('father')
    mother = Person('motner')
    father.work()
    mother.work()
    print(Person.money)

    执行结果

    father 工作,赚了1000块

    motner 工作,赚了1000块

    2000


    对于静态属性的修改,应该使用类名直接修改,就不会出现不一致的情况,因为类属性是共享的


    练习题,写一个类,完成一个功能,可以统计这个类有几个对象

    class Foo:
        count = 0
        def __init__(self):
            Foo.count += 1
    f1 = Foo()  #实例化一个对象
    f2 = Foo()  #实例化一个对象
    f3 = Foo()  #实例化一个对象
    print(Foo.count)

    执行结果

    3


    例2:可变数据类型当做类静态属性(有坑!)

    class Person:
        money = [0]  # money为一个列表
        def __init__(self, name):
            self.name = name
        def work(self):
            print(self.name, '工作,赚了1000块')
            self.money[0] += 1000
    
    father = Person('father')
    mother = Person('motner')
    father.work()
    mother.work()
    print(Person.money)

    执行结果

    father 工作,赚了1000块

    motner 工作,赚了1000块

    [2000]

    为什么是2000?

    blob.png


    例3:

    class Person:
        money = [0]  # money为一个列表
        def __init__(self, name):
            self.name = name
        def work(self):
            print(self.name, '工作,赚了1000块')
            self.money = [Person.money[0] + 1000]
    
    father = Person('father')
    mother = Person('motner')
    father.work()
    mother.work()
    print(Person.money)

    执行结果

    father 工作,赚了1000块

    motner 工作,赚了1000块

    [0]

    为什么结果是0?

    blob.png

    不管是类里面还是类外面,统一使用:类名.静态变量名

关键字