1. 组合
组合一般就是把横向之间几个没有关系的类放在一个类里面使用
先定义两个单独没有关系的类:
class Turtle:
def __init__(self, x):
self.num = x
class Fish:
def __init__(self, x):
self.num = x
再定义一个组合类:
class Pool:
def __init__(self,x,y):
self.Turtle=Turtle(x) #实例化一个乌龟对象,并且存入变量x
self.Fish=Fish(y) #实例化一个鱼的对象,并且存入变量y
def printNum(self):
print('水池里共有乌龟 %d 只,小鱼 %d 条'%(self.Turtle.num,self.Fish.num))
调用:
pool=Pool(1,10)
pool.printNum()
2. 类,类对象和实例对象 - - 三个不同的物种
class A:
count = 0; #count是一个类属性
a = A()
b = A()
c = A()
以上例子中,A指代的地址里存放的是一个类,但是定义完,A就是一个类对象;而abc是三个实例对象
接下来我们继续我们的实验:
↓
print(a.count)
print(b.count)
print(c.count)
初始的时候,实例对象的属性都是类属性的初始值。
↓
c.count+=10
print(a.count)
print(b.count)
print(c.count)
↓
然后我们对A这个类对象来进行修改
A.count+=100
print(a.count)
print(b.count)
print(c.count)
↓
为什么c.count=10?
: 因为c.count 开头+=10 相当于实例了一个属性,覆盖了父类的属性定义,实例属性已经指向了新的地址,跟原来的类属性地址无关了;
: 但是如果没有实例一个属性,则实例对象的属性仍然跟随着类属性的值,如ab
↓
但是实例属性不会这样,实例属性在实例对象创建时就实例化了:
↓
下面就用类属性和实例属性做一个对比:
class test:
count = 5 # 类属性
def __init__(self):
self.x=5 #实例属性
def printSelfX(self):
print(self.x)
Test=test()
Test.printSelfX()
print(Test.count)
可以看到:实例对象 的 实例属性和类属性的初始值 都是和 类对象的实例属性和类属性 一样。
可能忒拗口了咳咳咳,仔细看就理解了
↓
我们改变父类的 两个属性的值:
test.count=10
test.x=20
print(test.x)
print(test.count)
可以看到我们的父类对象的两个值已经被改变了,那么我们实例对象的两个值又会怎样呢?
↓
print('实例对象x:',Test.x)
print('类对象count:',Test.count)
可以看到,结论是:
实例属性在实例对象创建时就实例化了,与原父类属性无关
类属性需要实例对象进行赋值才会实例化,覆盖掉父类定义,否则始终跟随原父类属性改变
↓
再做一个实验:
当删除父类以后会怎样呢?
del test
print('实例对象x:',Test.x)
print('类对象count:',Test.count)
竟然仍然可以输出!
解释是这样的:
当删除了类对象test以后 仅仅是释放了类对象(标签) 但是类本身定义就是是static的静态方法,静态属性,仍然存在内存里。
但是退出程序以后,类和实例对象都会从内存释放。
↓
但是不能再用test类对象来实例化对象
# Test2 = test()
因为test这个类对象(标签)不再指向类的内存地址,无法用test类对象来实例化新的对象。
3. 什么是绑定?
python严格要求方法需要有实例才能被调用→ 这种限制其实就是python所谓的绑定概念;
错误示范:
class Db:
def printDb(): #没有self对象!!!
print('no zuo no die')
db = Db()
db.printDb() #实例化后,没有self参数没法工作!!!
正确示范:
class Db:
def printDb(self): #有self
print('im ok')
db = Db()
db.printDb() #实例化后,必须要self参数才可工作