巨蟒python全栈开发-第18天 核能来袭-类和类之间的关系

一.今日主要内容:

 

1.类与类之间的关系
在我们的世界中事物和事物之间总会有一些联系.
在面向对象中,类和类之间也可以产生相关的关系
(1)依赖关系
执行某个动作(方法)的时候,需要xxx来帮助你完成这个操作,此时的关系是最轻的.
随时可以更换另外一个东西来完成此操作

大象进冰箱&植物大战僵尸
(2)关联关系(在对象里面埋对象)

老师=>学校
A.一对一关系 self.girlFriend=girl
典型案例:你和你的女朋友

B.一对多关系(生活中,更多的是这种关系) self.teach_list=[t1,t2,t3]
一个学校,一堆老师

C.多对多关系

类中的关系:依赖关系最轻的,最重的是继承关系,关联关系是比较微妙的.

2.self到底是谁?
self:谁调用的就是谁.类型是根据调用方的对象来进行变换的(不一定是这个类)
super:与继承相关的.(表示的是父类)

3.关联关系=>组合=>聚合=>UML图(一看就会清晰明了了)(类与类之间的关系UML图)

4.特殊成员:(我们没有主动调用,而是自动调用)
__init__() #创建对象的时候初始化操作
__new__() #创建对象的时候,开辟内存

__call__() #对象()
__getitem__() #对象['冬瓜']
__setitem__() #对象['冬瓜']=值
__hash__() #可哈希 hash()

__enter__() #with 对象
__exit__() #结束with的时候

class A:
def __init__(self):
xxxx
a=A()

二.今日内容大纲:

1.依赖关系

2.关联关系

3.继承关系

4.特殊成员

三.今日内容详解:

1.依赖关系

(1)依赖关系例题

class Person:
    def play(self,tools):     #通过参数的传递把另外一个类的对象传递进来
        tools.run()
        print('很开心,我能玩儿游戏了')

class Computer():
    def run(self):
        print('电脑开机,可以运行')

class Phone():
    def run(self):
        print('手机开机,可以运行了')

c=Computer()
phone=Phone()

p=Person()
p.play(phone)

(2)

#典型的依赖关系,可以像方法进行缩进优化(思考)
#这个题目还是有一定的深度的,在攻击力里边的写法
#写一个植物大战僵尸

# 1.植物
# 打僵尸,将是掉血
# 2.僵尸
# 吃植物,植物掉血
#自己写的版本,漏洞很多,思考的灵活性还是不够
class plant():
    def __init__(self,name,blood,gjl):
        self.name=name
        self.blood=blood
        self.gjl=gjl

    def skill(self,js):
        js.blood-=self.gjl
        print(f'僵尸掉血{self.gjl},还剩下{js.blood}')

class jiangshi():

    def __init__(self,name,blood,gjl):
        self.name=name
        self.blood=blood
        self.gjl=gjl

    def j_skill(self,zw):
        zw.blood-=self.gjl
        print(f'植物掉血{self.gjl},还剩下{zw.blood}')

zhiwu=plant('大冬瓜',100,1)
js=jiangshi('小僵尸',20,2)

zhiwu.skill(js)
js.j_skill(zhiwu)

# pjf=pj_fight()
# pjf.play(zhiwu)

#老师讲解

class plant():
    def __init__(self,name,hp,ad):
        self.name = name
        self.hp = hp
        self.ad = ad

    def attack(self,js):    #注意这里需要名字js
        print('植物攻击僵尸')
        js.hp-=self.ad
        print(f'僵尸掉血{self.ad},还剩下{js.hp}')

class jiangshi():

    def __init__(self,name,hp,ad):
        self.name = name
        self.hp = hp
        self.ad = ad

    def attack(self,zw):
        print('僵尸咬植物')
        zw.hp-=self.ad
        print(f"植物掉血{self.ad},还剩{zw.hp}")

wd = plant('大冬瓜', 100, 1)
js = jiangshi('小僵尸', 20, 2)

wd.attack(js)
wd.attack(js)
wd.attack(js)

js.attack(wd)
js.attack(wd)
js.attack(wd)
js.attack(wd)

#人狗大战&西门庆与武松大战都可以写了

 

2.关联关系

(1)一对一关系

class Boy:
    def __init__(self,name,girlFriend=None):
        #在初始化的时候可以给一个对象的属性设置成另一个 类的对象
        self.name=name
        self.girlFriend=girlFriend      #一个男孩有一个女朋友

    def chi(self):
        if self.girlFriend:
            print(f'带着他的女朋友{self.girlFriend.name}去吃饭')
        else:
            print('单身狗,吃什么吃?滚去学习')
    def movie(self):
        if self.girlFriend:
            print(f'带着他的女朋友{self.girlFriend.name}去看电影')
        else:
            print('单身狗,吃什么吃?滚去学习')

class Girl:
    def __init__(self,name):
        self.name=name
#第一步
b=Boy('宝浪')
g=Girl('孙艺珍')
b.chi()

#第二步
#alex给宝浪介绍了一个女朋友,孙艺珍
b=Boy('宝浪')
g=Girl('孙艺珍')
b.girlFriend=g
b.chi()

#第三步
b=Boy('宝浪')
g=Girl('孙艺珍')
g2=Girl('梁咏琪')      #在这里换了女朋友
b.girlFriend=g2       #换了个女朋友
b.chi()

(2)

#一对多关系(使用率最高的关系),超级重点
#这个通过列表的创建,列表的添加,for循环列表
#与 初始化,招聘老师,上课老师 进行方法对应
class School():
    def __init__(self,name):
        self.teach_list=[]  #这里要装多个老师
                            #注意这里搞了一个列表             #创建
        self.name=name
        self.hehe='呵呵'
        #初始化时候,可以给一些属性

    def zhaopin(self,teach):                                  #添加
        self.teach_list.append(teach)

    def shangke(self):
        for t in self.teach_list:                           #循环执行
            t.work()
class Teacher:
    def __init__(self,name):
        self.name=name
    def work(self):
        print(f'{self.name}在上课')

lnh=School('老男孩')
t1=Teacher('武sir')
t2=Teacher('太白')
t3=Teacher('哪吒')
t4=Teacher('女神')
t5=Teacher('日天')
t6=Teacher('宝浪')

lnh.zhaopin(t1)                                             #在这个地方添加的是实例化后的对象
lnh.zhaopin(t2)
lnh.zhaopin(t3)
lnh.zhaopin(t4)
lnh.zhaopin(t5)
lnh.zhaopin(t6)

lnh.shangke()   #一执行,就把上边的全部执行了
                  #因为上课中用到的是for遍历列表中的细信息

 

3.继承关系

(1)

class Base:
    def chi(self):
        print('我会吃')

#派生类=>就是子类
class Foo(Base):   #这个类继承了Base类,Foo类是对Base的一个扩展
    def he(self):
        print('我会喝')
f=Foo()
f.chi()
f.he()

(2)

#注意名称的描述
class Cat:  #父类=>基类(超类)
    def catch_mouse(self):
        print("猫可以抓老鼠")

class BosiCat(Cat): #子类=>派生类
    pass

(3)

class Foo:
    pass
print(hash(Foo))    #可哈希
print(hash(Foo()))  #可哈希

#总结:我们写好的类和创建的对象默认都是可哈希的

class Foo:
    __hash__=None
print(hash(Foo))        #可哈希
print(hash(Foo()))      #unhashable type: 'Foo'

#类永远是可哈希的,但是加上__hash__=None,
# 对象就不可哈希了

(4)

#利用字典进行调用
class Foo:
    def chi(self):
        print('我爱吃鱼')
class Bar:
    def chi(self):
        print('我爱吃肉')
dic ={Foo:Foo(),Bar:Bar()}

for k,v in dic.items():
    v.chi()

(5)

#利用字典调用=>升级
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)

(6)self系列

# self中 先找自己的,再找父类的

#对比函数进行回顾:
# 类名  => 变量名 ->相同的道理
# def func():
#     pass
#
# an = func
# an()
View Code
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
class Foo(Base):
    pass
obj = Foo(123)
obj.func1()

'''
结果:
123
'''
View Code
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)

class Foo(Base):
    def func1(self):
        print("Foo. func1", self.num)

obj = Foo(123)
obj.func1()

'''
结果:
Foo. func1 123
'''
View Code
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
        self.func2()
    def func2(self):
        print("Base.func2")

class Foo(Base):
    def func2(self):
        print("Foo.func2")
obj = Foo(123)
obj.func1()

'''
结果:
123
Foo.func2
'''
View Code
class Base:
    def __init__(self, num):
        self.num = num

    def func1(self):
        print(self.num)
        self.func2()

    def func2(self):
        print(111, self.num)

class Foo(Base):
     def func2(self):
        print(222, self.num)

lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
 obj.func2()

'''
结果:
111 1
111 2
222 3
'''
View Code
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
        self.func2()
    def func2(self):
        print(111, self.num)

class Foo(Base):
    def func2(self):
        print(222, self.num)

lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
    obj.func1()

'''
结果:
1
111 1
2
111 2
3
222 3
'''
View Code

 

4.特殊成员

(1)

class Foo:
    def __init__(self):
        print('初始化操作,在创建对象的时候自动调用这个方法')

f=Foo()     #自动执行__init__()
f.__init__()    #第一次这么写,以后不要这么写

#上边两行是等价的

(2)

# 回顾:三大器1
# lst=[]
# lst.__iter__()

#回顾内置函数
# lst=[1,2,3,4]
# it=iter(lst)
# print(it.__next__())
# print(next(it))

(3)

#callable  可调用的  判断xxx是否是可调用的

# 曾经的例子:
# def func():
#     pass
# print(callable(func))
# func=3
# print(callable(func))   #此时变成不可调用的

# class Foo:
#     def __init__(self):
#         print('初始化操作,在创建对象的时候自动调用这个方法')
# f=Foo()             #结果:初始化操作,在创建对象的时候自动调用这个方法
# print(callable(f))  #False  说明对象不可调用
#

#__call__()的作用:
# class Foo:
#     def __init__(self):
#         print('初始化操作,在创建对象的时候自动调用这个方法')
#
#     #为了对象能够被调用而生的    f()
#     def __call__(self, *args, **kwargs):
#         print('我是对象()')
# f=Foo()                     #初始化操作,在创建对象的时候自动调用这个方法
# f()                         #我是对象(),   调用的是__call__内的东西
# print(callable(f))          #True

(4)

#__getitem__   字典,元组,列表都是用的这个  (给值)

# class Foo:
#     #对象[]
#     def __getitem__(self, item):
#         print('item=',item)
#         print('你执行了__getitem__')
#         return  '哈哈'
# f=Foo()                     #初始化操作,在创建对象的时候自动调用这个方法
# print(f['李嘉诚'])

'''
结果:
item= 李嘉诚
你执行了__getitem__
哈哈
'''

(5)

#__setItem__()方法

# class Foo:
#     def __setitem__(self, key, value):
#         print("key, ", key)
#         print("value, ", value)
# f=Foo()
# f['jay'] = "林俊杰"

'''
结果:
key,  jay
value,  林俊杰
'''

(6)

# __delitem__()方法

# class Foo:
#     def __delitem__(self, key):
#         print('key=',key)
# f=Foo()
# del f['哈哈']

'''
结果:
key= 哈哈
'''

(7)

# __enter__() 方法
#__exit__()方法

# class Foo:
# # with 对象:
#     def __enter__(self):
#         print("我是enter")
#     # with 对象: 代码执行完毕. 最后执行这里
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         print("我叫exit")
# f=Foo()
# with f:
#     print("我是哈哈哈哈")

'''
结果:
我是enter
我是哈哈哈哈
我叫exit
'''

(8)

# class Foo:
#     def __init__(self): # 初始化操作
#         print("我是init,  我是老二")
#         print("初始化操作. 在创建对象的时候自动调用这个方法")
#
#     def __new__(cls, *args, **kwargs): # 创建, 它是真正的构造方法,  可以开辟内存
#         print("我是new. 我是老大")  #在开辟内存之前可以放东西
#         return object.__new__(cls)

(9)

# lst = ["孙艺珍", "李金珠", "井柏然"]
#
# lst[2] # =>自动的调用__getitem__()

(10)

面向对象编程的执行流程=>
1.加载类=>给类创建一个名称空间=>主要存放类变量
2.创建对象=>先找类=>根据类来开辟内存=>
执行类中的__new__() -> 执行__init__() -> 返回对象

(11)

#__str__()  and __repr__()
class Student:
    def __init__(self,name,no,gender,cls,age):
        self.name=name
        self.no=no
        self.gender=gender
        self.cls=cls
        self.age=age

      # 遇到出不来,两个都尝试一下
      # 如果只是内存地址,再写另一个试试
    #这个对象字符串的表示
    # def __str__(self):   #返回该对象的字符串表示形式
    #     return f'{self.name},{self.no},{self.gender}'

    # def __repr__(self):     #该对象的官方的字符串表示形式
    #     return f'{self.name},{self.no},{self.gender}'
s = Student("冬瓜", "3", "", "S18", "31")
print(s)

作业讲解:记得补充:

 

posted @ 2018-12-19 17:28  studybrother  阅读(232)  评论(0编辑  收藏  举报