PYTHON-面向对象 类 绑定方法

面向对象三大特性(*****)

1继承
1. 什么是继承
继承是一种新建类的方式,新建的类称之为子类/派生类,被继承的类称之为父类/基类/超类

继承与现实生活中的继承一个意思 (例如 小明继承小明他爹财产 房子)
一个东西b继承了另一个东西a b就拥有a的内容
在代码中
一个类b继承了另一个类a b这个类 就拥有了a中所有属性

继承有3个特点:
1. 子类可以遗传/重用父类的属性(解决类与类之间代码冗余的问题)
2. 在python中一个子类可以同时继承多个父类
3. 在继承的背景下,类分为两种:新式类,经典类
新式类:但凡继承object类的子类,以及该子类的子子孙孙都是新式类
在python3中一个类即便是没有显式地继承任何类,默认就继承object类,
即在python3中所有类都是新式类
经典类:没有继承object类的子类,以及该子类的子子孙孙都是经典类
强调:只有在python2中才有经典类
在python2中如果一个类没有显式地继承任何类,并不会自动继承object类

2. 为何要用继承:减少类与类之间的代码冗余
使用场景:
例如: 你的项目中需要两种对象 老师和学生
分析发现 老师和学生有很多相似之处 都有 姓名 性别 年龄
将相同的部分属性 抽取到一个共同父类中person

3. 如何继承 :先抽象再继承(抽取比较像的部分继承属性)
# 在python中继承的特点?单继承(用一个父类)&多继承(用多个父类)
class Person:
共有的属性
name
age
gender
def sleep():
print(大家都需要睡觉 睡觉的过程也相同)

def attendClass():
print("听到上课铃声 要去教室")
===================
x = 2
class Foo:
x = 1
pass
obj = Foo()
obj.x = 3

print(obj.x)


2 抽象类
什么是抽象类 **
与java一样,python也有抽象类的概念但是同样需要借助模块实现,
抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

抽象类是一个介于类和接口直接的一个概念,
同时具备类和接口的部分特性,可以用来实现归一化设计

import abc #利用abc模块实现抽象类

class All_file(metaclass=abc.ABCMeta):
all_type='file'
@abc.abstractmethod #定义抽象方法,无需实现功能
def read(self):
'子类必须定义读功能'
pass


3. 属性查找(*****)
在没有出现菱形继承的情况下,属性的查找是按照从左往右的顺序一个分支一个分支的找下去
在单继承背景下,无论是新式类还是经典类属性查找顺序都一样
先obj->类->父类->...

在出现菱形继承(一个子类继承的多个分支最终汇聚到一个非object类)的情况下,
在多继承背景下,如果一个子类继承了多个分支,但是多个分支最终汇聚到一个非object类(菱形继承问题)
面试常问问题*****
(新式类 继承object类的才是新式类 广度优先)
(经典类 如果你直接创建一个类在2.7中就是经典类 深度优先)
新式类:广度优先查找,按照从左往右的顺序一个分支一个分支的找下去,在最后一个分支才去查找顶级类
obj->A->B->E->C->F->D->G->object
经典类(没有object类):深度优先查找,按照从左往右的顺序一个分支一个分支的找下去,在第一个分支就查找顶级类
obj->A->B->E->G->C->F->D
(.mro()参考该对象所属类的mro查找)

类有两种属性:数据属性和函数属性
1. 类的数据属性是所有对象共享的
2. 类的函数属性是绑定给对象用的

在obj.name会先从obj自己的名称空间里找name,
找不到则去类中找,类也找不到就找父类...
最后都找不到就抛出异常

4. 派生(*****)
在子类中定义自己的属性,如果与父类的属性重名,那以自己的为准.

在子类派生的新方法中重用父类的功能:
方式一:指名道姓地调用某一个类的函数
特点:类名.函数名(对象,参数1,参数2,...)==>
1. 与继承无关
2. 没有自动传值的效果

class OldboyPerson:#父类
school="oldboy"
def __init__(self,name,age,gender):
self.name=name
self.age=age
self.gender=gender
class Teacher(OldboyPerson):#子类
def __init__(self,name,age,gender,level,salary):
OldboyPerson.__init__(self,name,age,gender)
# super(Teacher, self).__init__(name, age, gender)
self.level = level
self.salary = salary

方式二:super()得到一个特殊的对象,该对象专门用来引用父类的属性
特点:super(自己的类名, self).父类的方法(参数1,参数2,...) == >
super().父类的方法(参数1,参数2,...)
1. 严格依赖继承,super会完全参照类的mro列表去便历父类中属性依次查找
2. 有自动传值的效果


当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性
(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,
那么调用新增的属性时,就以自己为准了。

class Riven(Hero):
camp='Noxus'
def attack(self,enemy): #在自己这里定义新的attack,不再使用父类的attack,且不会影响父类
print('from riven')
def fly(self): #在自己这里定义新的
print('%s is flying' %self.nickname)

在子类中,新建的重名的函数属性,在编辑函数内功能的时候,
有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,
即:类名.func(),此时就与调用普通函数无异了,
因此即便是self参数也要为其传值

class Riven(Hero):
camp='Noxus'
def __init__(self,nickname,aggressivity,life_value,skin):
Hero.__init__(self,nickname,aggressivity,life_value) #调用父类功能
self.skin=skin #新属性
def attack(self,enemy): #在自己这里定义新的attack,不再使用父类的attack,且不会影响父类
Hero.attack(self,enemy) #调用功能
print('from riven')
def fly(self): #在自己这里定义新的
print('%s is flying' %self.nickname)

r1=Riven('锐雯雯',57,200,'比基尼')
r1.fly()
print(r1.skin)

'''
运行结果
锐雯雯 is flying
比基尼

'''
posted @ 2018-10-23 18:20 DU-JUN 阅读(...) 评论(...) 编辑 收藏