⾯向对象的三⼤属性
1,⾯向对象中的继承表⽰的是类与类之间的关系(什么是什么的关系),在python3中,所有的类都会默认继承object类,继承了object类的所有类都是新式类,如果⼀个类没有继承任何⽗类,那么__bas__属性就会显⽰<class 'object'>。
2,继承可以分为单继承和多继承。
# 单继承
class Parent:pass
class Son(Parent):pass# 继承关系
# Son继承了Parent
print(Son.__bas__) # 内置的属性
print(Parent.__bas__) # 内置的属性
# 多继承
class Parent1:pass
class Parent2(Parent1):收据本
pass
class鹿鞭片的作用与功效
Parent3:pass
class Son(Parent2,Parent3):pass# 继承关系
print(Parent2.__bas__)
print(Son.__bas__)
View Code
3,对象使⽤名字的顺序: 先找对象⾃⼰内存空间中的,再找对象⾃⼰类中的,再找⽗类中的。
class Animal:
role = 'Animal'
def__init__(lf,name,hp,ad):
lf.name = name # 对象属性属性
lf.hp = hp #⾎量
lf.ad = ad #攻击⼒
def eat(lf):
print('%s吃药回⾎了'%lf.name)
class Person(Animal):
r = 'Person'
def attack(lf,dog): # 派⽣⽅法
print("%s攻击了%s"%(lf.name,dog.name))
def eat2(lf):
print('执⾏了Person类的eat⽅法')
< = 100
< -= 10
lf.hp += 10
class Dog(A肃然起敬的意思
nimal):
def bite(lf,person): # 派⽣⽅法
print("%s咬了%s" % (lf.name, person.name))
# 继承中的init
alex = Person('alex',10,5)
le)
print(alex.__dict__)
dog = Dog('teddy',100,20)
print(dog.__dict__)
# 继承中的派⽣⽅法
alex = Person('alex',10,5)
dog = Dog('teddy',100,20)
alex.attack(dog)
dog.bite(alex)
# 继承⽗类的⽅法:⾃⼰没有同名⽅法
alex = Person('alex',10,5)
dog = Dog('teddy',100,20)
alex.eat2()
alex.eat()
dog.eat()
View Code
# class Animal:
# def __init__(lf,name,x,kind):
# lf.name = name
# lf.x = x
# lf.kind = kind
# def eat(lf):
# print('%s is eating'%lf.name)
#
# def drink(lf):
# print('%s is drinking'%lf.name)
#
# class Cat(Animal):
# def climb(lf):
# print('%s is climbing'%lf.name)
#
# class Dog(Animal):
# def watch_door(lf):
# print('%s is watching door'%lf.name)
# 1.确认韩国r级电影排行
⾃⼰没有init⽅法
# 2.看看有没有⽗类
# 3.发现⽗类Animal有init
# 4.看着⽗类的init⽅法来传参数
#tom = Cat('tom','公','招财猫') # 实例化对象
# tom.eat = '猫粮'
# print(Cat.__dict__) # Cat.__dict__ Cat类的命名空间中的所有名字
# print(tom.__dict__) # tom.__dict__ 对象的命名空间中的所有名字
# tom.eat() # 先找⾃⼰对象的内存空间再找类的空间再找⽗类的空间
# tom.climb() # 先找⾃⼰的内存空间再找类的空间
View Code
4,lf.名字的时候,不要看lf当前在哪个类⾥,要看这个lf到底是谁的对象class Parent:
def func(lf):
print('in parent func')
def__init__(lf):
lf.func()
class Son(Parent):
def func(lf):
print('in son func')
s = Son()
View Code
5,object 类
class A:
# '''
# 这是⼀个类
# '''
pass
a = A()
print(A.__dict__) # 双下⽅法魔术⽅法
# 创建⼀个空对象
# 调⽤init⽅法 —— 调⽤了么?调⽤了
# 将初始化之后的对象返回调⽤处
View Code
6,在单继承中,如何给⼀个类的对象增加派⽣属性呢?
详见如下代码:
class Animal:
def__init__(lf,name,hp,ad):
lf.name = name # 对象属开国大典手抄报
性属性
lf.hp = hp #⾎量
lf.ad = ad #攻击⼒
def eat(lf):
print('eating in Animal')
lf.hp += 20
class Person(Animal):
def__init__(lf,name,hp,ad,x):
# Animal.__init__(lf,name,hp,ad)
#次为⽅法⼀
# super(Person,lf).__init__(name,hp,ad)
#此为⽅法⼆
super().__init__(name, hp, ad)
#此为⽅法⼆简写(常⽤)
# 在单继承中,super负责找到当前类所在的⽗类,在这个时候不需要再⼿动传lf
lf.x = x # 这个就是增加的派⽣属性
< = 100
def attack(lf,dog): # 派⽣⽅法
print("%s攻击了%s"%(lf.name,dog.name))
def eat(lf): # 重写
super().eat() # 在类内使⽤ super()⽅法找⽗类的⽅法
print('eating in Person')
< -= 50
class Dog(Animal):
def__init__(lf,name,hp,ad,kind):
Animal.__init__(lf,name,hp,ad)
lf.kind = kind # 派⽣属性
def bite(lf,person): # 派⽣⽅法
print("%s咬了%s" % (lf.name, person.name))
alex = Person("zhangsan",100,10,"male") # 实例化
#print(alex.__dict__)
# tg = Dog('到哥',100,50,'藏獒')
# print(tg.__dict__)
# ⽗类有eat ⼦类没有
# alex.eat() # 找⽗类的
# ⼦类有eat 不管⽗类中有没有
# alex.eat() # 找⼦类的
# 当⼦类中有,但是我想要调⽗类的
# Animal.eat(alps前景色
ex) #指名道姓
# super(Person,alex).eat() # super(⼦类名,⼦类对象)⽅法 —— ⼀般不⽤
# ⼦类⽗类都有eat⽅法,我想执⾏⽗类的eat和⼦类的eat
#alex.eat() # 执⾏⼦类的eat
View Code
7,多继承之钻⽯继承
对于多继承中的新式类,寻找名字的顺应该遵循⼴度优先。类名.mro() 可以查询⼴度优先的遍历顺序。例如下⾯的程序:
class A:
def func(lf):
print('A')
class B(A):
pass
# def func(lf):
# print('B')
class C(A):
pass
# def func(lf):
# print('C')
class D(B):
pass
# def func(lf):
# print('D')
class E(B,C):
pass
# def func(lf):
# print('E')
class F(D,E):
pass
# def fu乡村鬼事
nc(lf):
# print('F')
f = F()
f.func()
()) # 查看⼴度优先的遍历顺序,其遍历顺序为 F-D-E-B-C-A
Vi新年快乐图
ew Code
【附】:pyrhon3 中的新式类遵循的⼴度优先算法图⽰
8,当遇到多继承和super时,应遵循以下的情况:
(1)找到这个对象对应的类。
(2)将这个类的所有⽗类都找到画成⼀个图
(3)根据图写出⼴度优先的顺序
(4)再看代码,看代码的时候要根据⼴度优先顺序图来找对应的super 例如以下程序:
class A:
def func(lf):
print('A')
class B(A):
def func(lf):
super().func()
print('B')
class C(A):
def func(lf):
super().func()
print('C')
class D(B,C):
def func(lf):
super().func()
print('D')
d = D()
d.f拔河图片
unc() #结果为 A-C-B-D
View Code
该程序分析过程如下:
【注】:supper(),在单继承中就是单纯的寻找⽗类,在多继承中就是根据⼦节点所在图的 mro 顺序找寻下⼀个类。
9,python 2中的经典类的多继承问题
【注】:经典类只在 python2 版本才存在,且必须不继承object。它在遍历的时候遵循深度优先算法,⽽且没有mro⽅法和super()⽅法。在python2 的版本中,必须⼿动继承object 类,才是新式类。它在遍历的时候遵循⼴度优先算法,在新式类中,有mro⽅法和super()⽅法,但是在2.X版本的解释器中,必须传参数(⼦类名,⼦类对象)。
【附】:python2 中的经典类中遵循的深度优先算法图⽰
⼆:多态
1,什么是多态?
在java中,多态就是在⼀个类之下发展出来的多个类的对象都可以作为参数传⼊这⾥。⽽在python中不需要刻意实现多态,因为python本⾝⾃带多态效果。
2,鸭⼦类型
不是通过具体的继承关系来约束某些类中必须有哪些⽅法名,⽽是通过⼀种约定俗成的概念来保证在多个类中相似的功能叫相同的名字。class QQpay():
def pay(lf,money):
print('使⽤qq⽀付了%s元'%money)
class Wechatpay():
def pay(lf,money):
print('使⽤微信⽀付了%s元'%money)
def pay(pay_obj,money):
pay_obj.pay(money)
a=QQpay()
pay(a,100)
View Code
三:封装
1,什么是封装?
封装就是隐藏对象的属性和实现细节,仅对外提供公共访问⽅式。
2,私有静态变量
⾸先定义⼀个私有的名字:就是在私有的名字前⾯加两条下划线,如 __N = 'aaa'
class A:
__N = 'aaa'# 静态变量
def func(lf):
print(A.__N) # 在类的内部使⽤正常