day26--静态属性类方法静态方法组合继承
Posted _慕
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了day26--静态属性类方法静态方法组合继承相关的知识,希望对你有一定的参考价值。
一、静态属性
class Room: tag=1 def __init__(self,name,owner,width,length,heigh): self.name=name self.owner=owner self.width=width self.length=length self.heigh=heigh @property def cal_area(self): # print(\'%s 住的 %s 总面积是%s\' % (self.owner,self.name, self.width * self.length)) return self.width * self.length
r1=Room(\'厕所\',\'alex\',100,100,100000)
print(r1.cal_area)
要点:@property + return 把公共函数变成数据属性,实例调用的调用的时候去掉小括号,像调用普通属性一样调用它。
二、类方法
class Room: tag=1 def __init__(self,name,owner,width,length,heigh): self.name=name self.owner=owner self.width=width self.length=length self.heigh=heigh @classmethod def tell_info(cls,x): print(cls) print(\'-->\',cls.tag,x) r1=Room(\'厕所\',\'alex\',100,100,100000) Room.tell_info(10) #输出: <class \'__main__.Room\'> --> 1 10
要点:@classmethod 和 cls 专门供类使用的方法,类调用的时候不用传实例,也可以被实例调用(不建议这么做,本来就是划给类的方法,你还去调用它,四不是四傻)
三、静态方法
是一种普通函数,位于类定义的命名空间中,不会对任何实例类型进行操作,python为我们内置了函数staticmethod来把类中的函数定义成静态方法。
应用场景:编写类时需要采用很多不同的方式来创建实例,而我们只有一个__init__函数,此时静态方法就派上用场了。
class Room: tag=1 def __init__(self,name,owner,width,length,heigh): self.name=name self.owner=owner self.width=width self.length=length self.heigh=heigh @staticmethod def wash_body(a,b,c): print(\'%s %s %s正在洗澡\' %(a,b,c)) Room.wash_body(\'alex\',\'yuanhao\',\'wupeiqi\') print(Room.__dict__) r1=Room(\'厕所\',\'alex\',100,100,100000) print(r1.__dict__) r1.wash_body(\'alex\',\'yuanhao\',\'wupeiqi\') #输出: alex yuanhao wupeiqi正在洗澡 { \'wash_body\': <staticmethod object at 0x000000000261B438>, ..... } {\'name\': \'厕所\', \'owner\': \'alex\', \'width\': 100, \'length\': 100, \'heigh\': 100000} alex yuanhao wupeiqi正在洗澡
class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @staticmethod def now(): #用Date.now()的形式去产生实例,该实例用的是当前时间 t=time.localtime() #获取结构化的时间格式 return Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回 @staticmethod def tomorrow():#用Date.tomorrow()的形式去产生实例,该实例用的是明天的时间 t=time.localtime(time.time()+86400) return Date(t.tm_year,t.tm_mon,t.tm_mday) a=Date(\'1987\',11,27) #自己定义时间 b=Date.now() #采用当前时间 c=Date.tomorrow() #采用明天的时间 print(a.year,a.month,a.day) print(b.year,b.month,b.day) print(c.year,c.month,c.day)
要点:@staticmethod 只是名义上归属类管理,不能调用类变量、实例变量,只是类的工具包。
四、组合
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合。
用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系。
当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好。
class Trunk: pass class Head: pass class Person: def __init__(self,id_num,name): self.id_num=id_num self.name=name self.trunk=Trunk() self.head=Head() p1=Person(\'111111\',\'alex\') print(p1.name) print(p1.id_num) print(p1.__dict__) #输出: alex 111111 {\'id_num\': \'111111\', \'name\': \'alex\', \'trunk\': <__main__.Trunk object at 0x000000000290B358>, \'head\': <__main__.Head object at 0x000000000290B390>}
class School: def __init__(self,name,addr): self.name=name self.addr=addr def zhao_sheng(self): print(\'%s 正在招生\' %self.name) class Course: def __init__(self,name,price,period,school): self.name=name self.price=price self.period=period self.school=school s1=School(\'oldboy\',\'北京\') s2=School(\'oldboy\',\'南京\') s3=School(\'oldboy\',\'东京\') c1=Course(\'linux\',10,\'1h\',\'oldboy 北京\') c2=Course(\'linux\',10,\'1h\',s1)
要点:把s1当做参数传进去,可以不写死。
五、继承
继承是一种创建新的类的方式,在python中,新建的类可以继承自一个或者多个父类,原始类称为基类或超类,新建的类称为派生类或子类。
class Grandfather: pass class Father(Grandfather): #单继承 Father是派生类,grandfather 是基类 pass class son(Father,Grandfather): #多继承 pass
继承使用产生的场景:如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同时我们不可能从头开始写一个类B,这就用到了类的继承的概念。通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用。
除了继承与派生的概念还有一个概念是需要提出的那就是:组合。组合就是指在一个类中以另外一个类的对象作为数据属性,成为类的组合。
组合与继承两者到底什么的关系?1.继承的方式:通过继承建立了派生类与基类的关系,两者之间是“是”的关系。当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师 2.组合的方式:用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程(当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好)
class School: def __init__(self,name,addr): self.name=name self.addr=addr def zhao_sheng(self): print(\'%s 正在招生\' %self.name) class Course: def __init__(self,name,price,period,school): self.name=name self.price=price self.period=period self.school=school s1=School(\'北大\',\'北京\') c1=Course(\'linux\',10,\'1h\',s1) print(c1.name) #linux print(c1.school) # <__main__.School object at 0x02182330> print(c1.school.name) # 北大 print(c1.school.addr) # 北京
在这个例子中呢,创建了两个类,一个是学校类一个是课程类。需要将课程类与学校类进行相关联的时候,继承在这里是不合适的,那我们采用组合的方式来对这两个类进行关联,这样就在实例化一门课程的时候把学校的信息进行关联。
子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。
class Dad: \'这个是爸爸类\' money=10 def __init__(self,name): print(\'爸爸\') self.name=name def hit_son(self): print(\'%s 正在打儿子\' %self.name) class Son(Dad): money = 1000000000009 def __init__(self,name,age): self.name=name self.age=age def hit_son(self): print(\'来自儿子类\')
接口继承(抽象类):
从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。
抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 。
import abc class All_file(metaclass=abc.ABCMeta): @abc.abstractmethod def read(self): pass @abc.abstractmethod def write(self): pass class Disk(All_file): def read(self): print(\'disk read\') def write(self): print(\'disk write\') class Cdrom(All_file): def read(self): print(\'cdrom read\') def write(self): print(\'cdrom write\') class Mem(All_file): def read(self): print(\'mem read\') def write(self): print(\'mem write\') m1=Mem() m1.read() m1.write()
父类规定子类中必须实现的方法,但父类不实现(基类接口进行规范化子类)。
顺序继承:
class A: # def test(self): # print(\'A\') pass class B(A): # def test(self): # print(\'B\') pass class C(A): def test(self): print(\'C\') # pass class D(B): # def test(self): # print(\'D\') pass class E(C): def test(self): print(\'E\') # pass class F(D,E): # def test(self): # print(\'F\') pass f1=F() f1.test() #经典类:F->D->B->A-->E--> print(F.__mro__) #F-->D->B-->E--->C--->A新式类 #输出: E (<class \'__main__.F\'>, <class \'__main__.D\'>, <class \'__main__.B\'>, <class \'__main__.E\'>, <class \'__main__.C\'>, <class \'__main__.A\'>, <class \'object\'>)
继承的顺序:A为父类
新式类找的顺序:
在子类中调用父类的方法super():
class Vehicle1: Country=\'China\' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print(\'开动啦\') print(\'开动啦\') class Subway(Vehicle1): def __init__(self,name,speed,load,power,line): # Vehicle.__init__(self,name,speed,load,power) super().__init__(name,speed,load,power) #super(__class__,self).__init__(name,speed,load,power) self.line=line def show_info(self): print(self.name,self.speed,self.load,self.power,self.line) def run(self): # Vehicle.run(self) super().run() print(\'%s %s 线,开动啦\' %(self.name,self.line)) line13=Subway(\'北京地铁\',\'10km/s\',1000000000,\'电\',13) line13.show_info() line13.run() print(line13.__class__)
当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次(注意注意注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表)。
学习资料来源:海峰老师
以上是关于day26--静态属性类方法静态方法组合继承的主要内容,如果未能解决你的问题,请参考以下文章
2018-07-04-Python全栈开发day25-静态属性类方法静态方法以及组合