python类与类之间的关系

在面向对象中,类和类之间也可以产生相关的关系
类中的关系: 依赖关系是最轻的,最重的是继承关系,关联关系是比较微妙的

依赖关系
执行某个动作的时候,需要xxx来帮助完成这个操作,此时的关系是最轻的.
随时可以更换另外一个东西来完成此操作

class Person:
    def f1(self,tools):     # 通过参数的传递把另外一个类的对象传递进来
        tools.run()
        print('皮一下很开心')
class Computer:
    def run(self):
        print('电脑开机运行')
class Phone:
    def run(self):
        print('手机开机')
c = Computer()
a = Phone()
p = Person()
p.f1(a)         #把Phone类的对象a传递给Person的f1方法作为参数
结果
手机开机
皮一下很开心

事例二
植物大战僵尸
class Plant:
    def __init__(self,hp,ad):
        self.hp = hp
        self.ad = ad
    def attack(self,js):
        print('植物攻击僵尸')
        js.hp -= self.ad
        print(f'僵尸掉血{self.ad},剩余{js.hp}')
class JiangShi:
    def __init__(self,hp,ad):
        self.hp = hp
        self.ad = ad
    def attack(self,zw):
        print('僵尸咬植物')
        zw.hp -= self.ad
        print(f'植物掉血{self.ad},剩余{zw.hp}')
zw = Plant(100,11)
js = JiangShi(80,15)
zw.attack(js)
zw.attack(js)
js.attack(zw)
js.attack(zw)
结果
植物攻击僵尸
僵尸掉血11,剩余69
植物攻击僵尸
僵尸掉血11,剩余58
僵尸咬植物
植物掉血15,剩余85
僵尸咬植物
植物掉血15,剩余70

关联关系
对象里面包含对象

一对一关系
class Boy:
    def __init__(self,name,girFriend=None):
        self.name = name
        self.girFriend = girFriend
    def play(self):
        if self.girFriend:
            print(f'{self.name}带着他女朋友{self.girFriend.name}去吃饭')
        else:
            print('单身狗,还吃什么饭')
    def movie(self):
        if self.girFriend:
            print(f'{self.name}带着他女朋友{self.girFriend.name}去看电影')
        else:
            print('单身狗,还看什么电影')
class Girl:
    def __init__(self,name):
        self.name = name
b = Boy('刘昊然')
g = Girl('刘丽')
b.play()

b.girFriend = g
b.play()

g2 = Girl('王萌')
b.girFriend = g2
b.movie()


一对多关系
self.teach_list = [t1,t2,...]
class School:
    def __init__(self,name):
        self.teach_list = []
    def zhaopin(self,teach):
        self.teach_list.append(teach)
    def shangke(self):
        for i in self.teach_list:
            i.work()
class Teacher:
    def __init__(self,name):
        self.name = name
    def work(self):
        print(f'{self.name}在上课')
lnh = School('测试')
t1 = Teacher('赵老师')
t2 = Teacher('刘老师')
lnh.zhaopin(t1)
lnh.zhaopin(t2)
lnh.shangke()
结果
赵老师在上课
刘老师在上课

继承关系

class Base:         #父类又叫基类又叫超类
    def chi(self):
        print('吃饭')
class Foo(Base):    #子类又叫派生类,这个类继承了Base类,Foo类是对Base的一个扩展
    def he(self):
        print('喝水')
f = Foo()
f.chi()
f.he()
print(hash(Foo))    #默认类和创建的对象都是可哈希的
print(hash(Foo()))
结果
吃饭
喝水
-9223371912599947772
-9223371912597968945

去掉可哈希
__hash__ = None
class Base:
    def chi(self):
        print('吃饭')
class Foo(Base):
    __hash__ = None     # 当前类的对象不可哈希
    def he(self):
        print('喝水')
f = Foo()
f.chi()
f.he()
print(hash(Foo))    # 类名永远可哈希
print(hash(Foo()))  # TypeError: unhashable type: 'Foo'

类名相当于变量名

class Foo:
    def chi(self,food):
        print('吃鱼和',food)
class Bar:
    def chi(self,food):
        print('吃肉和',food)
dic = {Foo:'面包',Bar:'牛奶'}
for k,v in dic.items():
    k().chi(v)
结果
吃鱼和 面包
吃肉和 牛奶

self:谁调用的就是谁,类型是根据调用方的对象来进行变换的
super:表示的是父类

特殊成员:
__init__()  # 创建对象的时候初始化操作
__call__()  # 对象()
__getitem__()   # 对象[哈哈]
__setitem__()   # 对象[哈哈] = 值
__new__()   # 创建对象的时候.开辟内存
__hash__()  # 可哈希 hash()

__call__ 
对象后面加括号,触发执行
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        print('__call__')

obj = Foo()  # 执行 __init__
obj()  # 执行 __call__
结果
__call__

事例2
class Foo:
    def __init__(self):                 # 初始化操作
        print('我是init,我是第二')

    def __new__(cls, *args, **kwargs):  # 创建,是真正的构造方法,可以开辟内存
        print('我是new,我是第一')
        return object.__new__(cls)

    def __call__(self, *args, **kwargs): # 对象()   
        print('我是对象call')

    def __getitem__(self, item):        # 对象[]
        print('item',item)
        print('我是getite')

    def __setitem__(self, key, value):  # 对象[key] = value
        print('key',key)
        print('value',value)
Foo()
f = Foo()          # 自动执行__init__()
f()                # 调用__call__()
print(callable(f)) # 对象()
print(f['娃哈哈']) #自动调用__getitem__()
f['']='刘丽'     #自动的调用__getitem__()
结果
我是new,我是第一
我是init,我是第二
我是new,我是第一
我是init,我是第二
我是对象call
True
item 娃哈哈
我是getite
None
key 人
value 刘丽


事例3
class Foo:
    def __init__(self,name):
        self.name=name

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        self.__dict__[key]=value
    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print('del obj.key时,我执行')
        self.__dict__.pop(item)

f1=Foo('sb')
f1['age']=18
f1['age1']=19
print(f1.__dict__)
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)
结果
{'name': 'sb', 'age': 18, 'age1': 19}
del obj.key时,我执行
del obj[key]时,我执行
{'name': 'alex'}


事例4
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    #这个对象字符串的表示
    def __str__(self):  #返回该对象的字符串表示形式
        return f'{self.name},{self.age}'
    def __repr__(self):  #该对象的官方的字符串表示形式
        return f'{self.name},{self.age}'
s = Person('bob','18')
print(s)
结果
bob,18

事例5
class B:
    def __str__(self):
        return 'str : class B'
    def __repr__(self):
        return 'repr : class B'
b = B()
print('%s' % b)     #这个执行的是__str__函数方法
print('%r' % b)     #这个执行的是__repr__函数方法
结果
str : class B 
repr : class B


__del__
析构方法,当对象在内存中被释放时,自动触发执行
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class Foo:

    def __del__(self):
        print('执行我啦')

f1=Foo()
del f1
print('------->')
结果
执行我啦
------->

 

posted @ 2018-12-30 15:39  清茶i  阅读(327)  评论(0编辑  收藏  举报