类命名空间

在一个类中它的函数(方法)属于动态属性,直接定义的变量属于静态属性

首先先定义一个类,并在这个类里面加入静态变量、属性等然后将一个对象实例化

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学习日记(二十三) 类命名空间和组合的更多相关文章

  1. Python学习日记(二十五) 接口类、抽象类、多态

    接口类 继承有两种用途:继承基类的方法,并且做出自己的改变或扩展(代码重用)和声明某个子类兼容于某基类,定义一个接口类interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子 ...

  2. Python学习日记(二十八) hashlib模块、configparse模块、logging模块

    hashlib模块 主要提供字符加密算法功能,如md5.sha1.sha224.sha512.sha384等,这里的加密算法称为摘要算法.什么是摘要算法?它又称为哈希算法.散列算法,它通过一个函数把任 ...

  3. Python学习(二十三)—— 前端基础之jQuery

    转载自http://www.cnblogs.com/liwenzhou/p/8178806.html 一.jQuery入门 jQuery是一个轻量级的.兼容多浏览器的JavaScript库. jQue ...

  4. Python学习日记(二十七) 反射和几个内置函数

    isinstance() 判断isinstance(obj,cls)中obj是否是cls类的对象 class Person: def __init__(self,name): self.name = ...

  5. Python学习日记day10------函数的命名空间、作用域与闭合函数

    1,参数陷阱 如果默认参数的只是一个可变数据类型,那么每一次调用的时候,如果不传值就共用这个数据类型的资源. 2,三元运算 c=a if a>b else b#如果a>b返回a,否则,返回 ...

  6. Python学习日记(二十六) 封装和几个装饰器函数

    封装 广义上的封装,它其实是一种面向对象的思想,它能够保护代码;狭义上的封装是面向对象三大特性之一,能把属性和方法都藏起来不让人看见 私有属性 私有属性表示方式即在一个属性名前加上两个双下划线 cla ...

  7. Python学习日记(二十四) 继承

    继承 什么是继承?就是一个派生类(derived class)继承基类(base class)的字段和方法.一个类可以被多个类继承;在python中,一个类可以继承多个类. 父类可以称为基类和超类,而 ...

  8. Python学习日记(二十二) 初识面向对象

    引子 假设我们要开发一个关于飞机大战的游戏,那么游戏的里面就会有两个角色,分别是属于玩家操控的战机和敌方的战机,并且两个战机都有不同的技能或攻击方式,现在我们用自己目前所学的去写出下面的这些代码: d ...

  9. Python学习日记(二十一) 异常处理

    程序中异常的类型 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Exception 常规错误的基 ...

随机推荐

  1. elementUI 的el-dialog作为子组件,父组件如何控制其关闭的按钮

    这里有三点需要说明: 1. 使用:before-close="closeHandle" 将其 $emit() 出去 2. 取消按钮 也需要$emeit出去 3. 控制对话框显示隐藏 ...

  2. 运维笔记--ubuntu安装指定版本的RabbitMQ

    场景描述: 日常开发or生产环境经常会需要安装指定版本的软件,出于和其他软件的配合兼容性,以及稳定性的考虑. 现在我们的需求是安装指定版本的RabbitMQ,版本号: 操作步骤: 注意事项: 异常处理 ...

  3. Robot Framwork关键字驱动+RedwoodHQ安装

    一.Robot Framwork介绍 Robot Framwork是一款python编写的功能框架.具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行. ...

  4. 【Redis】Redis 事务

    Redis 事务介绍 Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证: 批量操作在发送 EXEC 命令前被放入队列缓存. 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败 ...

  5. SNP功能注释网站合集

    这篇文章是对SNP位点功能注释在线网站的一个总结帖. 软件排名不分先后,优先顺序可以看推荐指数. 彩蛋在最后,请坚持看完 1.GWAS4D, 推荐指数:**** 网址:http://mulinlab. ...

  6. 元数据Meta

    元数据,指的是“除了字段外的所有内容”,例如排序方式.数据库表名.人类可读的单数或者复数名等等.所有的这些都是非必须的,甚至元数据本身对模型也是非必须的. 在模型中增加元数据,需要在模型类中添加一个子 ...

  7. [LeetCode] 156. Binary Tree Upside Down 二叉树的上下颠倒

    Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that ...

  8. Tomcat一些说明

    嗯,昨天将有关JDK的知识稍微整理了一下,现在稍微整理一下有关Tomcat的! 1:Tomcat是什么? Tomcat是当今世界上使用最为广泛的.开源免费的Servlet/JSP容器,其主要功能是用于 ...

  9. 【OpenCV开发】OpenCV3后IPLimage转换成MAT的问题

    IplImage* img1 = cvCreateImage(cvGetSize(resizeRes), IPL_DEPTH_8U, 1);//创建目标图像 Mat test = img1;  报错 ...

  10. 记录一次使用iisnode部署node项目遇到的坑!

    前言:最近因为项目原因,需要在IIS下部署node项目,在此之前,曾经部署过类似的项目,因此在这次部署还算比较顺利,只是在其中遇到了几个比较坑的问题,所以这次使用博客记录下来,如有园友遇到过类似问题, ...