Python学习日记(二十三) 类命名空间和组合
类命名空间
在一个类中它的函数(方法)属于动态属性,直接定义的变量属于静态属性
首先先定义一个类,并在这个类里面加入静态变量、属性等然后将一个对象实例化
class Fighter: #定义一个战机的类price = 5000 #静态变量def __init__(self,name,speed,atk,hp):self.name = nameself.speed = speedself.atk = atkself.hp = hpdef Attack(self):print('本次攻击造成了%s的伤害'%(self.atk)) f1 = Fighter('J-20',1000,400,5000) print(f1.__dict__) #{'name': 'J-20', 'speed': 1000, 'atk': 400, 'hp': 5000}
那如何修改一个静态属性,我们可以用类名.静态变量名等于我们想要赋值的内容就可以修改
Fighter.price = 4500 print(Fighter.__dict__) #{'__module__': '__main__', 'price': 4500, '__init__': <function Fighter.__init__ at 0x0000000002148950>, 'Attack': <function Fighter.Attack at 0x0000000002148A60>, '__dict__': <attribute '__dict__' of 'Fighter' objects>, '__weakref__': <attribute '__weakref__' of 'Fighter' objects>, '__doc__': None}
如果我们用__dict__方法去修改结果是不行的
Fighter.__dict__['price'] = 2500 print(Fighter.__dict__) #TypeError: 'mappingproxy' object does not support item assignment
关系图:
当我们使用f1.price的时候,f1会先在自己的命名空间去找,它会发现自己的内存空间里没有这个price,然后在通过类对象指针找到Fighter的命名空间,取得price这个变量
而Fighter.price是直接从自己的命名空间中取得,找到就返回
注意:只有实例化出来的对象才能找到类,而类并不能找到每一个对象
如果我们想用实例化出来的一个对象去修改类里面的静态变量,该怎么做?
可以看出在这里直接修改这个静态变量我们并没有修改成功,而是在我们的这个self;'字典'里新增了一个price属性
f1.price = 4500 print(f1.__dict__) #{'name': 'J-20', 'speed': 1000, 'atk': 400, 'hp': 5000, 'price': 4500} print(Fighter.__dict__) #{'__module__': '__main__', 'price': 5000, '__init__': <function Fighter.__init__ at 0x0000000002448950>, 'Attack': <function Fighter.Attack at 0x0000000002448A60>,'__dict__': <attribute '__dict__' of 'Fighter' objects>,'__weakref__': <attribute '__weakref__' of 'Fighter' objects>, '__doc__': None}
那么再想用回类里面的静态变量的话只能删除price
del f1.price print(f1.price) #5000 print(f1.__dict__) #{'name': 'J-20', 'speed': 1000, 'atk': 400, 'hp': 5000}
对于像上面这种不可变数据类型而言,类变量最好用类操作
现在我们把这个静态变量改成列表的类型,可以看到我们运用修改索引值的方式成功修改了原来的列表的元素
class Fighter: #定义一个战机的类price = [5000] #静态变量def __init__(self,name,speed,atk,hp):self.name = nameself.speed = speedself.atk = atkself.hp = hpdef Attack(self):print('本次攻击造成了%s的伤害'%(self.atk)) f1 = Fighter('J-20',1000,400,5000) f1.price[0] = 6000 print(f1.__dict__) #{'name': 'J-20', 'speed': 1000, 'atk': 400, 'hp': 5000} print(Fighter.__dict__) #{'__module__': '__main__', 'price': [6000], '__init__': <function Fighter.__init__ at 0x00000000027D8950>,'Attack': <function Fighter.Attack at 0x00000000027D8A60>, '__dict__': <attribute '__dict__' of 'Fighter' objects>,'__weakref__': <attribute '__weakref__' of 'Fighter' objects>, '__doc__': None}
这是因为像这种可变数据类型(列表),它所改变的值不影响它本身的内存地址,像price它所指向的还是列表这个内存地址,所以改变了它的内部的值不会有太大的影响
但是如果我们这样写的话就相当于开辟了一个新的内存空间存放新的列表了
f1.price = [6000] print(f1.__dict__) #{'name': 'J-20', 'speed': 1000, 'atk': 400, 'hp': 5000, 'price': [6000]} print(Fighter.__dict__) #{'__module__': '__main__', 'price': [5000], '__init__': <function Fighter.__init__ at 0x00000000025A8950>, 'Attack': <function Fighter.Attack at 0x00000000025A8A60>, '__dict__': <attribute '__dict__' of 'Fighter' objects>, '__weakref__': <attribute '__weakref__' of 'Fighter' objects>, '__doc__': None}
最后静态变量和函数名不要相同
一个例子:创建一个类,每实例化一个对象就计数,最终所有的对象都共享这个数据
class Counter():count = 0def __init__(self):Counter.count += 1 print(Counter.count) #0 c1 = Counter() print(Counter.count) #1 c2 = Counter() print(Counter.count) #2
绑定方法:
一个类没有__init__也可以实例化,self仍能把自己传给f1
class Person:def fuc(self):print('Walking...') f1 = Person() print(f1.__dict__) #{} f1.fuc() #Walking...
现在再定义一个函数
def func():print('Testing...') class Person:def fuc(self):print('Walking...') f1 = Person() print(func) #<function func at 0x00000000027C8730> print(Person.fuc) #<function Person.fuc at 0x00000000027C8A60> print(f1.fuc) #<bound method Person.fuc of <__main__.Person object at 0x0000000002737A58>> print(f1) #<__main__.Person object at 0x0000000002737A58>
当对象去调用方法的时候就是把里面的值传给这个方法那么他们之间就发生了一种绑定关系
import
当我们引入一个包的时候就相当于实例化了一个对象
组合
表示在一个类中以另外一个类的对象作为数据属性,称为类的组合
我们先声明三个类玩家的战机类、敌机的类和武器的类:
class Fighter: #定义一个玩家战机的类def __init__(self,name,atk,hp,speed,money):self.name = nameself.atk = atkself.hp = hpself.speed = speedself.money = 0def playerAttack(self,enemyfighter):enemyfighter.hp -= self.atkclass EnemyFighter: #定义个敌机的类def __init__(self,name,atk,hp,speed,kind):self.name = nameself.atk = atkself.hp = hpself.speed = speedself.kind = kinddef enemyFighterAttack(self,fighter):fighter.hp -= self.atkclass Weapon: #定义一个武器的类def __init__(self,name,atk,durability,price):self.name = nameself.atk = atkself.durability = durabilityself.price = priceplayerFighter1 = Fighter('Player1',200,1500,300,0) Boss1 = EnemyFighter('lazerBoss',1000,7000,50,'Boss') w1 = Weapon('AMR-123',1000,10,300) print(w1.__dict__) #{'name': 'AMR-123', 'atk': 1000, 'durability': 10, 'price': 300} print(Boss1.__dict__) #{'name': 'lazerBoss', 'atk': 1000, 'hp': 7000, 'speed': 50, 'kind': 'Boss'} print(playerFighter1.__dict__) #{'name': 'Player1', 'atk': 200, 'hp': 1500, 'speed': 300, 'money': 0}
如何将我们的装备装备到我们玩家的战机上?在玩家的身上写一个get_weapon函数让一个武器的对象作为参数传给这个函数,再让玩家或得到武器的这些属性
class Fighter: #定义一个玩家战机的类def __init__(self,name,atk,hp,speed,money = 0):self.name = nameself.atk = atkself.hp = hpself.speed = speedself.money = moneydef playerAttack(self,enemyfighter):enemyfighter.hp -= self.atkdef get_weapon(self,weapon): #玩家获得武器属性的函数if self.money >= weapon.price: #如果玩家的金钱大于武器的价格self.money -= weapon.price self.weapon = weapon #给玩家添加武器的属性self.hp += weapon.maxHpself.atk += weapon.atkelse:print('余额不足请先充值!')class EnemyFighter: #定义个敌机的类def __init__(self,name,atk,hp,speed,kind):self.name = nameself.atk = atkself.hp = hpself.speed = speedself.kind = kinddef enemyFighterAttack(self,fighter):fighter.hp -= self.atkclass Weapon: #定义一个武器的类def __init__(self,name,atk,maxHp,durability,price):self.name = nameself.atk = atkself.maxHp = maxHpself.durability = durabilityself.price = priceplayerFighter1 = Fighter('Player1',200,1500,300,500) Boss1 = EnemyFighter('lazerBoss',1000,7000,50,'Boss') w1 = Weapon('AMR-123',1000,1000,10,300) print(playerFighter1.__dict__)#{'name': 'Player1', 'atk': 200, 'hp': 1500, 'speed': 300, 'money': 500} playerFighter1.get_weapon(w1) print(playerFighter1.__dict__)#{'name': 'Player1', 'atk': 1200, 'hp': 2500, 'speed': 300, 'money': 200, 'weapon':<__main__.Weapon object at 0x000000000280D518>}
现在我们给武器设计一个招数,给怪物一个致命一击
class Fighter: #定义一个玩家战机的类def __init__(self,name,atk,hp,speed,money = 0):self.name = nameself.atk = atkself.hp = hpself.speed = speedself.money = moneydef playerAttack(self,enemyfighter):enemyfighter.hp -= self.atkdef get_weapon(self,weapon): #玩家获得武器属性的函数if self.money >= weapon.price: #如果玩家的金钱大于武器的价格self.money -= weapon.priceself.weapon = weapon #给玩家添加武器的属性self.hp += weapon.maxHpself.atk += weapon.atkelse:print('余额不足请先充值!')class EnemyFighter: #定义个敌机的类def __init__(self,name,atk,hp,speed,kind):self.name = nameself.atk = atkself.hp = hpself.speed = speedself.kind = kinddef enemyFighterAttack(self,fighter):fighter.hp -= self.atkclass Weapon: #定义一个武器的类def __init__(self,name,atk,maxHp,durability,price):self.name = nameself.atk = atkself.maxHp = maxHpself.durability = durabilityself.price = pricedef lazerBullet(self,enemyFighter,fighter):if self.durability > 0:enemyFighter.hp -= self.atk*2 + fighter.atkself.durability -= 5else:print('您的武器耐久度为0,不可再使用!请重新充值!')playerFighter1 = Fighter('Player1',200,1500,300,500) Boss1 = EnemyFighter('lazerBoss',1000,7000,50,'Boss') w1 = Weapon('AMR-123',1000,1000,10,300) #初始的怪物和玩家属性 print(Boss1.__dict__) #{'name': 'lazerBoss', 'atk': 1000, 'hp': 7000, 'speed': 50, 'kind': 'Boss'} print(playerFighter1.__dict__) #{'name': 'Player1', 'atk': 200, 'hp': 1500, 'speed': 300, 'money': 500} #玩家装备上武器后属性 playerFighter1.get_weapon(w1) print(playerFighter1.__dict__) #{'name': 'Player1', 'atk': 1200, 'hp': 2500, 'speed': 300, 'money': 200, 'weapon': <__main__.Weapon object at 0x000000000280D518>} #第一回合玩家用武器大招攻击 playerFighter1.weapon.lazerBullet(Boss1,playerFighter1) print(Boss1.__dict__) #{'name': 'lazerBoss', 'atk': 1000, 'hp': 3800, 'speed': 50, 'kind': 'Boss'} #第二回合Boss攻击玩家 Boss1.enemyFighterAttack(playerFighter1) print(playerFighter1.__dict__) #{'name': 'Player1', 'atk': 1200, 'hp': 1500, 'speed': 300, 'money': 200, 'weapon': <__main__.Weapon object at 0x000000000279D4A8>} #第三回合玩家用武器大招攻击 playerFighter1.weapon.lazerBullet(Boss1,playerFighter1) print(Boss1.__dict__) #{'name': 'lazerBoss', 'atk': 1000, 'hp': 600, 'speed': 50, 'kind': 'Boss'} playerFighter1.weapon.lazerBullet(Boss1,playerFighter1) #您的武器耐久度为0,不可再使用!请重新充值! print(Boss1.__dict__) #{'name': 'lazerBoss', 'atk': 1000, 'hp': 600, 'speed': 50, 'kind': 'Boss'}
组合练习
1.用组合的方法求这个图形的面积,假设这里大圆半径为10,小圆半径为
from math import pi as P class Cicle:def __init__(self,r):self.r = rdef S(self):return P*self.r**2def L(self):return 2*P*self.r class Ring:def __init__(self,outside_r,inside_r):self.outside_c = Cicle(outside_r)self.inside_c = Cicle(inside_r)def ret_S(self):return self.outside_c.S() - self.inside_c.S()def ret_L(self):return self.outside_c.L() + self.inside_c.L() ring = Ring(10,5) print(ring.ret_S()) #235.61944901923448 print(ring.ret_L()) #94.24777960769379
2.创建一个老师类,老师有生日、课程,生日和课程可以是一个类,用组合的方式表示
class Teacher:def __init__(self,name,age,gender,course,birthday):self.name = nameself.age = ageself.gender = genderself.course = courseself.birthday = birthday class Course:def __init__(self,name,price,period):self.name = nameself.price = priceself.period = period class Birthday:def __init__(self,year,month,day):self.year = yearself.month = monthself.day = day p1 = Teacher('Jackson',25,'male',Course('python',15000,'7 months'),Birthday(1994,6,12)) print(p1.__dict__) #{'name': 'Jackson', 'age': 25, 'gender': 'male', 'course': <__main__.Course object at 0x00000000024AD390>, 'birthday': <__main__.Birthday object at 0x00000000024AD400>} print(p1.course.name,p1.course.price,p1.course.period) #python 15000 7 months print(p1.birthday.year,p1.birthday.month,p1.birthday.day) #1994 6 12
转载于:https://www.cnblogs.com/Fantac/p/11466679.html
Python学习日记(二十三) 类命名空间和组合相关推荐
- Python学习日记(二十五) 接口类、抽象类、多态
接口类 继承有两种用途:继承基类的方法,并且做出自己的改变或扩展(代码重用)和声明某个子类兼容于某基类,定义一个接口类interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子 ...
- python学习笔记(二十三) -- 多进程和多线程
目录 多线程多进程的意义 多进程的使用 方式一(fork): 只能在Unix/Linux/Mac系统下执行,windows不可以 方式二(multiprocessing.Process): 全平台通 ...
- Python学习日记(二十八) hashlib模块、configparse模块、logging模块
hashlib模块 主要提供字符加密算法功能,如md5.sha1.sha224.sha512.sha384等,这里的加密算法称为摘要算法.什么是摘要算法?它又称为哈希算法.散列算法,它通过一个函数把任 ...
- Python学习日记(二十七) 反射和几个内置函数
isinstance() 判断isinstance(obj,cls)中obj是否是cls类的对象 class Person:def __init__(self,name):self.name = na ...
- 【Python学习系列二十三】Scikit_Learn库降维方法(矩阵分解)-PCAFA
1主成分分析PCA 1.1 精确PCA和似然估计 PCA基于最大方差的正交变量分解多维数据集.在scikit-learn库中,PCA的实现是先通过fit方法计算n维的特征值和特征向量,然后通过tran ...
- Python学习日记-第二十三天-飞机大战(游戏背景设计思路)
系列文章目录 目标 ·背景简体滚动的思路确定 ·显示游戏背景 前言 这一章节是讲述的飞机大战游戏背景的设计思路细节. 一.背景简体滚动的思路确定 ·游戏启动后,背景图像 会连续不断的向下移动 ·视觉上 ...
- Python学习日记(二十六) 封装和几个装饰器函数
封装 广义上的封装,它其实是一种面向对象的思想,它能够保护代码;狭义上的封装是面向对象三大特性之一,能把属性和方法都藏起来不让人看见 私有属性 私有属性表示方式即在一个属性名前加上两个双下划线 cla ...
- Python学习日记(二十四) 继承
继承 什么是继承?就是一个派生类(derived class)继承基类(base class)的字段和方法.一个类可以被多个类继承;在python中,一个类可以继承多个类. 父类可以称为基类和超类,而 ...
- Python学习日记(二十二) 初识面向对象
引子 假设我们要开发一个关于飞机大战的游戏,那么游戏的里面就会有两个角色,分别是属于玩家操控的战机和敌方的战机,并且两个战机都有不同的技能或攻击方式,现在我们用自己目前所学的去写出下面的这些代码: d ...
最新文章
- Hide the common top menu in Ubuntu 12.04
- <a>标签带参数跳转并在下一个页面接收
- 专访|黄铁军:人工智能不会以人为中心,但不要为此失落
- java step1:基础知识5(java中Timer和TimerTask的使用)
- Java数据结构和算法:位运算
- html alert 的三种方式
- 前端学习(2331):angular之图片的使用
- 【HUST】网安|计算机网络安全实验|实验一 TCP协议漏洞及利用
- 翻译助手-免费翻译助手下载
- 微信小程序 + shiro 实现登录(安全管理) —— 保姆级教学
- 2020-11-01 Mybatis TypeAlise、resultMap、日志settings
- hadoop 结合zookeeper 高可用 优化新特性
- 【欧拉计划第 5 题】最小公倍数 Smallest multiple
- Ruby学习记录 - 安装Ruby
- [Unity3D]添加音效说明
- 第3章 Pandas数据处理(3.7-3.8)_Python数据科学手册学习笔记
- webpack 3.0 + 从切图仔到前端工程师-姜威-专题视频课程
- loading的使用
- 那些曾经的转正工作总结...
- 一文看懂25个神经网络模型,神经网络神经元模型
热门文章
- 网页制作 HTML设为首页和加入收藏_动力节点Java学院整理
- 阿里云语音服务配合alertmanager实现电话告警
- 海天酱油为美味而战,引领调味行业不断向前
- [Codevs P1391]伊吹萃香
- 软件测试笔记2——什么是软件测试及软件测试分类
- elasticsearch实践篇: 智能运输产品
- 无线基站定位服务器,android 基站定位api
- Windows 上安装charm-crypto
- 百度网盘免费jdk1.8中文chm和jdk1.9中文chm下载(不要积分点个赞就好)
- 如何用PHP实现图片与视频合成,PHP-php把图片组合成视频