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

对象之间的交互

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

#!/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变成字符串了,它不能执行

改成

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?

例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?

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逸鹏说道

我为NET狂面试题-基础篇-答案

面向过程: 答案:图片只贴核心代码,完整代码请打开解决项目查看 (答案不唯一,官方答案只供参考,若有错误欢迎提出~) 99乘法表 https://githu...

36113
来自专栏青玉伏案

算法导论之插入排序和归并排序

  作为一名前线的码农不时地看一下算法和数据结构还是很有必要的,虽然《算法导论》这本书很难啃,但还是有必要啃一下的。算法这东西和某种编程语言关系不大,在大学的课...

2417
来自专栏Java呓语

原型模式(克隆生成对象)

暂时抛弃掉之前的上下文(机器人 Samu与主人 Alice),创建型模式总不能很好对应机器人的上下文。

1086
来自专栏菩提树下的杨过

字符编码-使用c#研究

微软的那个臭屁的JOEL(就是写《JOEL说软件》的那个牛人)曾说:“每一位软件开发人员必须、绝对要至少具备UNICODE与字符集知识(没有任何例外)”,我也常...

2007
来自专栏逸鹏说道

我为NET狂官方面试题-基础篇

最近帮人过一遍C#基础,出了点题目,有需要的同志拿走 答案不唯一,官方答案只供参考,若有错误欢迎提出~ 答案明天发 面向过程 99乘法表 ? 用循环来输出以...

3309
来自专栏GreenLeaves

Jquery dom搜索之siblings()方法

      如果给定一个dom的元素集合的算则其对象,siblings()方法允许我们在dom树中搜索这个元素集合的同胞元素,并匹配这些元素构造一个新的对象,J...

2347
来自专栏Java爬坑系列

【JAVA零基础入门系列】Day8 Java的控制流程

  什么是控制流程?简单来说就是控制程序运行逻辑的,因为程序一般而言不会直接一步运行到底,而是需要加上一些判断,一些循环等等。举个栗子,就好比你准备出门买个苹果...

24210
来自专栏Java帮帮-微信公众号-技术文章全总结

第九天 面向对象-类,封装,对象,private,this【悟空教程】

2406
来自专栏用户2442861的专栏

#define和typedef的用法与区别及面试问题

在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间,实例像:

6791
来自专栏进击的君君的前端之路

Math对象、数组、日期函数

1625

扫码关注云+社区

领取腾讯云代金券