类命名空间

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

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

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. jQuery.validator.addMethod自定义验证方法

    在开发中用到了jQuery的validate控件,有时需要自定义验证方法.我们可以通过jQuery.validator.addMethod()来实现,下面是例子: <!DOCTYPE html ...

  2. PAT 甲级 1080 Graduate Admission (30 分) (简单,结构体排序模拟)

    1080 Graduate Admission (30 分)   It is said that in 2011, there are about 100 graduate schools ready ...

  3. [LeetCode] 114. Flatten Binary Tree to Linked List 将二叉树展平为链表

    Given a binary tree, flatten it to a linked list in-place. For example, given the following tree: 1 ...

  4. [LeetCode] 787. Cheapest Flights Within K Stops K次转机内的最便宜航班

    There are n cities connected by m flights. Each fight starts from city u and arrives at v with a pri ...

  5. charles安装和使用(转)

    转发链接:https://blog.csdn.net/zhangxiang_1102/article/details/77855548

  6. 使用 Node.js 写一个代码生成器

    背景 第一次接触代码生成器用的是动软代码生成器,数据库设计好之后,一键生成后端 curd代码.之后也用过 CodeSmith , T4.目前市面上也有很多优秀的代码生成器,而且大部分都提供可视化界面操 ...

  7. consul多数据中心搭建 【h】

    自建IDC后面简称own.阿里云机房ali.腾讯云机房txown机房:内网10.10.10.0/24,边界节点,10.10.10.100/101.xxx.80.xxxali机房:内网10.10.10. ...

  8. namespace Measure

    namespace Measure { public delegate void DelegateTrigger(); public class HMeasureSYS : System.IDispo ...

  9. Markdown Html高级功能 测试用例

    插入音频 后台样式代码: #cnblogs_post_body .music { height: 140px; /*padding-bottom: 14.39%;*/ /* 16:9 */ posit ...

  10. 解决python中的Non-UTF-8 code starting with ‘\xbs4’ in file错误

    出现错误如下图: 主要原因为编辑python脚本使用的编辑器编码有问题.我使用的编辑器是notepad++,由于没有做Python语言编辑配置,默认使用的是ANSI编码(右下角位置有编码格式),如下: ...