python 类的进阶
面向对象的三大特性:封装,继承,多态
一 继承
抽象(由下到上)——>继承(由上到下)。
继承是什么是什么的关系,可以减少重复代码。
class People: pass class Animal: pass class Student(People,Animal): pass print(Student.__bases__)
print(People.__bases__)
输出:
(<class '__main__.People'>, <class '__main__.Animal'>)
(<class 'object'>,)
People,Animal成为Student的父类或基类。查看父类的方法是__bases__.。没有父类是默认继承Object类。
但凡继承了Object的类,称为新式类。
没有继承Object的类,称为经典类。
在python3中都是新式类。
类的继承,对象的名称空间
class People: def __init__(self,name,age): self.name=name self.age=age def walk(self): print('%s can walk'%self.name) class Student(People): pass s=Student('egon',25) print(s.__dict__) print(Student.__dict__) print(People.__dict__)
输出:
{'name': 'egon', 'age': 25} {'__module__': '__main__', '__doc__': None} {'__module__': '__main__', '__init__': <function People.__init__ at 0x000001E6B259ABF8>, 'walk': <function People.walk at 0x000001E6B259AF28>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
结论,对象的名称空间由__init__方法初始化决定。不管__init__是自己的还是继承父类的
子类可以继承父类的所有属性和方法,但是当子类的方法和属性与父类相同是,调用子类自己的方法,最典型的就是__init__方法。
如果想使用父类的方法,可以用super方法,这是新式类的方法,推荐使用。指明道姓那种是经典类。
P.S super(子类,子类的对象)=super( ),这指的就是子类的父类。
二 派生
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def walk(self): print('{} can walk '.format(self.name)) class Teacher: def __init__(self,name,age,sex,level,salary): People.__init__(self,name,age,sex) self.level=level self.salary=salary def teach(self): print('{} can teach'.format(self.name)) def walk(self): People.walk(self) print('{} is walking'.format(self.name)) t=Teacher('egon','male',50,10,2500) t.teach() t.walk()
输出:
egon can teach egon can walk egon is walking
派生和继承没有任何关系,派生只是带调用时,实名道姓的进项调用。这个例子 Teacher类并没有继承People类,完全能够执行成功。和Teacher类继承了People类完全一样的效果。
三 组合
是什么有什么的关系,作用是减少代码量。
class Date: def __init__(self,year,mon,day): self.year=year self.mon=mon self.day=day def tell_date(self): print('{}年{}月{}日'.format(self.year,self.mon,self.day)) class Teacher: def __init__(self,name,birth): self.name=name self.birth=birth class Student: def __init__(self,name,birth): self.name=name self.birth=birth birth=Date(1990,3,25) t=Teacher('egon',birth) t.birth.tell_date()
输出:
1990年3月25日
Student类同样可以调用birth变量。
类的组合,目前看到的都是一个类生成的对象作为一个参数传给另一个类。后面这个类可以通过调用变量的途径取到前一个类的属性。
四 举例
综合了 继承,派生,组合的应用,
class People: def __init__(self, name, birth): self.name = name self.birth = birth self.course=[] def tell_course(self): for i in self.course: i.tell_info() class Course: def __init__(self,name,price,period): self.name=name self.price=price self.period=period def tell_info(self): print( ''' info name:%s price:%s period:%s '''%(self.name,self.price,self.period) ) class Date: def __init__(self,year,mon,day): self.year=year self.mon=mon self.day=day def tell_info(self): print('{}年{}月{}日'.format(self.year,self.mon,self.day)) class Teacher(People): def __init__(self,name,birth,level,salary): People.__init__(self,name,birth) self.level=level self.salary=salary def teach(self): print('%s can teach'%self.name) class Student(People): def __init__(self,name,birth,group): People.__init__(self,name,birth) self.group=group def study(self): print('%s can study'%self.name) birth=Date(1990,10,25) python=Course('python',150,15800) linux=Course('linux',120,12000) egon=Teacher('egon',birth,10,30000) alex=Teacher('alex',birth,-10,-20000) alex.course.append(python) egon.course.append(python) egon.course.append(linux) alex.tell_course() print('========================') egon.tell_course()
输出:
info name:python price:150 period:15800 ======================== info name:python price:150 period:15800 info name:linux price:120 period:12000
五 pickle在对象中的应用
json是不支持对象格式的,所以压缩解压都是pckle。
对象,类实际是绑定关系,不可分割。所以,在一个单独是py文件中,没有类的情况下,解压对象,是会报错的。需要将这个py文件导入。
import pickle with open('1.txt','wb') as f: pickle.dump(egon,f) import func #这是关键,func.py文件 func.get()
import pickle #这就就是func.py文件 def get(): with open('1.txt','rb')as f: res=pickle.load(f) print(res.tell_course())
这样,ok了。