Python学习日记(二十三) 类命名空间和组合
类命名空间
在一个类中它的函数(方法)属于动态属性,直接定义的变量属于静态属性
首先先定义一个类,并在这个类里面加入静态变量、属性等然后将一个对象实例化
class Fighter: #定义一个战机的类
price = 5000 #静态变量
def __init__(self,name,speed,atk,hp):
self.name = name
self.speed = speed
self.atk = atk
self.hp = hp
def 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) #
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 = name
self.speed = speed
self.atk = atk
self.hp = hp
def 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 = 0
def __init__(self):
Counter.count += 1
print(Counter.count) #
c1 = Counter()
print(Counter.count) #
c2 = Counter()
print(Counter.count) #
绑定方法:
一个类没有__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 = name
self.atk = atk
self.hp = hp
self.speed = speed
self.money = 0
def playerAttack(self,enemyfighter):
enemyfighter.hp -= self.atk class EnemyFighter: #定义个敌机的类
def __init__(self,name,atk,hp,speed,kind):
self.name = name
self.atk = atk
self.hp = hp
self.speed = speed
self.kind = kind
def enemyFighterAttack(self,fighter):
fighter.hp -= self.atk class Weapon: #定义一个武器的类
def __init__(self,name,atk,durability,price):
self.name = name
self.atk = atk
self.durability = durability
self.price = price playerFighter1 = 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 = name
self.atk = atk
self.hp = hp
self.speed = speed
self.money = money
def playerAttack(self,enemyfighter):
enemyfighter.hp -= self.atk
def get_weapon(self,weapon): #玩家获得武器属性的函数
if self.money >= weapon.price: #如果玩家的金钱大于武器的价格
self.money -= weapon.price
self.weapon = weapon #给玩家添加武器的属性
self.hp += weapon.maxHp
self.atk += weapon.atk
else:
print('余额不足请先充值!') class EnemyFighter: #定义个敌机的类
def __init__(self,name,atk,hp,speed,kind):
self.name = name
self.atk = atk
self.hp = hp
self.speed = speed
self.kind = kind
def enemyFighterAttack(self,fighter):
fighter.hp -= self.atk class Weapon: #定义一个武器的类
def __init__(self,name,atk,maxHp,durability,price):
self.name = name
self.atk = atk
self.maxHp = maxHp
self.durability = durability
self.price = price playerFighter1 = 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 = name
self.atk = atk
self.hp = hp
self.speed = speed
self.money = money
def playerAttack(self,enemyfighter):
enemyfighter.hp -= self.atk
def get_weapon(self,weapon): #玩家获得武器属性的函数
if self.money >= weapon.price: #如果玩家的金钱大于武器的价格
self.money -= weapon.price
self.weapon = weapon #给玩家添加武器的属性
self.hp += weapon.maxHp
self.atk += weapon.atk
else:
print('余额不足请先充值!') class EnemyFighter: #定义个敌机的类
def __init__(self,name,atk,hp,speed,kind):
self.name = name
self.atk = atk
self.hp = hp
self.speed = speed
self.kind = kind
def enemyFighterAttack(self,fighter):
fighter.hp -= self.atk class Weapon: #定义一个武器的类
def __init__(self,name,atk,maxHp,durability,price):
self.name = name
self.atk = atk
self.maxHp = maxHp
self.durability = durability
self.price = price
def lazerBullet(self,enemyFighter,fighter):
if self.durability > 0:
enemyFighter.hp -= self.atk*2 + fighter.atk
self.durability -= 5
else:
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': , 'speed': 50, 'kind': 'Boss'}
print(playerFighter1.__dict__) #{'name': 'Player1', 'atk': , 'hp': , 'speed': 300, 'money': }
#玩家装备上武器后属性
playerFighter1.get_weapon(w1)
print(playerFighter1.__dict__) #{'name': 'Player1', 'atk': , 'hp': , 'speed': 300, 'money': ,
'weapon': <__main__.Weapon object at 0x000000000280D518>}
#第一回合玩家用武器大招攻击
playerFighter1.weapon.lazerBullet(Boss1,playerFighter1)
print(Boss1.__dict__) #{'name': 'lazerBoss', 'atk': 1000, 'hp': , 'speed': 50, 'kind': 'Boss'}
#第二回合Boss攻击玩家
Boss1.enemyFighterAttack(playerFighter1)
print(playerFighter1.__dict__) #{'name': 'Player1', 'atk': , 'hp': , 'speed': 300, 'money': 200,
'weapon': <__main__.Weapon object at 0x000000000279D4A8>}
#第三回合玩家用武器大招攻击
playerFighter1.weapon.lazerBullet(Boss1,playerFighter1)
print(Boss1.__dict__) #{'name': 'lazerBoss', 'atk': 1000, 'hp': , '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 = r
def S(self):
return P*self.r**2
def 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 = name
self.age = age
self.gender = gender
self.course = course
self.birthday = birthday
class Course:
def __init__(self,name,price,period):
self.name = name
self.price = price
self.period = period
class Birthday:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.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
Python学习日记(二十三) 类命名空间和组合的更多相关文章
- Python学习日记(二十五) 接口类、抽象类、多态
接口类 继承有两种用途:继承基类的方法,并且做出自己的改变或扩展(代码重用)和声明某个子类兼容于某基类,定义一个接口类interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子 ...
- Python学习日记(二十八) hashlib模块、configparse模块、logging模块
hashlib模块 主要提供字符加密算法功能,如md5.sha1.sha224.sha512.sha384等,这里的加密算法称为摘要算法.什么是摘要算法?它又称为哈希算法.散列算法,它通过一个函数把任 ...
- Python学习(二十三)—— 前端基础之jQuery
转载自http://www.cnblogs.com/liwenzhou/p/8178806.html 一.jQuery入门 jQuery是一个轻量级的.兼容多浏览器的JavaScript库. jQue ...
- Python学习日记(二十七) 反射和几个内置函数
isinstance() 判断isinstance(obj,cls)中obj是否是cls类的对象 class Person: def __init__(self,name): self.name = ...
- Python学习日记day10------函数的命名空间、作用域与闭合函数
1,参数陷阱 如果默认参数的只是一个可变数据类型,那么每一次调用的时候,如果不传值就共用这个数据类型的资源. 2,三元运算 c=a if a>b else b#如果a>b返回a,否则,返回 ...
- Python学习日记(二十六) 封装和几个装饰器函数
封装 广义上的封装,它其实是一种面向对象的思想,它能够保护代码;狭义上的封装是面向对象三大特性之一,能把属性和方法都藏起来不让人看见 私有属性 私有属性表示方式即在一个属性名前加上两个双下划线 cla ...
- Python学习日记(二十四) 继承
继承 什么是继承?就是一个派生类(derived class)继承基类(base class)的字段和方法.一个类可以被多个类继承;在python中,一个类可以继承多个类. 父类可以称为基类和超类,而 ...
- Python学习日记(二十二) 初识面向对象
引子 假设我们要开发一个关于飞机大战的游戏,那么游戏的里面就会有两个角色,分别是属于玩家操控的战机和敌方的战机,并且两个战机都有不同的技能或攻击方式,现在我们用自己目前所学的去写出下面的这些代码: d ...
- Python学习日记(二十一) 异常处理
程序中异常的类型 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Exception 常规错误的基 ...
随机推荐
- 如何自己构建一套EasyNVR这样的无插件流媒体服务器实现摄像机硬盘录像机的网页可视化直播
EasyNVR流媒体解决方案 EasyNVR能够通过简单的网络摄像机通道配置,将传统监控行业里面的高清网络摄像机IP Camera.NVR等具有RTSP协议输出的设备接入到EasyNVR,EasyNV ...
- [LeetCode] 140. Word Break II 单词拆分II
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add space ...
- Influx Sql系列教程零:安装及influx-cli使用姿势介绍
influxdb 时序数据库,因为实际业务中使用到了,然而并没有发现有特别好的文章,完整的介绍influx sql的使用姿势,因此记录下实际开发中学习的体会,主要参考来自于官方文档 Influx Qu ...
- ztree实现拖拽移动和复制
1.官网下载ztree:http://www.treejs.cn/v3/api.php 2.引入jquery.ztree.all.min.js 注意,这是基于jQuery的插件,请引入相关js 3.设 ...
- python局部变量和全局变量(6)
在python开发中,变量也是有生命周期的,一旦周期结束,程序会自动清理暂用的空间,释放内存,变量分为两者,一种是局部变量,一种是全局变量,两者具体有什么区别呢…… 一.局部变量 一般而言在函数内部或 ...
- SecureCRT字体、界面优化
SecureCRT字体.界面优化 本文是secureCRT的第三篇博文,也是目前secureCRT优化的最终篇.首次使用该软件时候.应该会设置字体和编码,接下来,将演示如何设置. 1. 字体.编码设置 ...
- QT 模拟Visio软件通过拖动搭建流程图
探索中.. 1 https://bbs.csdn.net/topics/390848708 https://www.cnblogs.com/chinese-zmm/archive/2010/10/10 ...
- linux命令及相关配置
hostname # 查看 hostname vim /etc/hostname # 修改hostname,重启后生效 vim /etc/resolv.conf 写入 nameserver 192.1 ...
- [转帖]Linux 下软链接和硬链接的区别
Linux 下软链接和硬链接的区别 http://os.51cto.com/art/201911/605267.htm 软连接 文件是小的 只是一个链接 删除和其他处理不影响 原始文件的计数 删除源文 ...
- 屏蔽组合键[CTRL+N]
https://www.cnblogs.com/gaodu2003/archive/2011/05/05/2037229.html …… const _KeyPressMask=$80000000; ...