首页 > 代码库 > day26--静态属性、类方法、静态方法、组合、继承

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--静态属性、类方法、静态方法、组合、继承