zoukankan      html  css  js  c++  java
  • python之静态、组合、继承

    一、python之静态

    1.1静态属性

    我们知道类既有函数属性又有数据属性,实例只有数据属性,我们在使用实例调用类的函数属性并运行时,总要带上函数后面的括号才能运行,不然总是调用函数的内存地址。

    问题:那么我们如何能像调用数据属性一样调用函数属性呢?

    类中提供了@property关键字,可以看成@property是一个装饰器,装饰器的作用是调用类的函数属性key值时,直接来运行该key值对应的函数。像是调用类的属性一样来直接调用并运行类的函数,具体操作如:

     1 class Room:
     2     def __init__(self,name,owner,width,length,heigth):
     3         self.Name=name
     4         self.Owner=owner
     5         self.Width=width
     6         self.Length=length
     7         self.Heigth=heigth
     8 
     9     @property
    10     def cal_area(self):
    11         return self.Width*self.Length
    12 
    13 r1=Room('客厅','czd',10,10,3)
    14 r2=Room('客厅','lzq',9,9.5,4)
    15 
    16 print(r1.cal_area)
    17 print(r2.cal_area)
    18 
    19 print(r1.Name)
    20 print(r2.Name)

    注意,当类中的函数有其他参数时(非self),加上@property关键字会报错,提示缺少必要的位置参数,猜想应该是装饰的问题,可能需要自定义装饰器才行。可以判断,@property的作用是:直接运行被装饰的函数,不能带参数,表面上看就是在被装饰的函数后面直接加括号。如:

    import time
    class Door():
        "门的类"
        address = "浙江省杭州市"
        def __init__(self,size,color,type):#构造函数
            "初始化门的数据"
            self.size = size
            self.color = color
            self.type = type
        @property
        def open(self):
            "门打开的方法"
            print("这个%s门打开了" %self.type)
        @property
        def off(self,time):
            "门关闭的方法"
            print("这个%s门关闭了,时间为;%s" %(self.type,time))
    door1 = Door(16, 'red', '木门')
    #调用数据属性
    print(door1.size)
    print(door1.address)
    #调用函数属性
    # door1.open()    #函数后面的括号每次都必须要带上
    #实例调用类的静态属性
    print(Door.__dict__)
    door1.open
    time1 = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
    # door1.off(time1)    #传参无效,应该要自定义对应的装饰器才行
    View Code

    1.2类方法
    类方法是将类本身作为对象进行操作的方法。他和静态方法的区别在于:不管这个方式是从实例调用还是从类调用,它都用第一个参数把类传递过来但是注意到self有特殊含义,它是指实例的本身,也就是说要使用self必须要先实例化才行。为了解决这个问题,我们引入另一个@classmethod装饰器后,就可以直接通过类来调用类的函数属性了(该函数带类的数据属性参数),如:

    class Room:
        tag = 1
    
        def __init__(self, name, owner, width, length, heigth):
            self.Name = name
            self.Owner = owner
            self.Width = width
            self.Length = length
            self.Heigth = heigth
    
        def cal_area(self):
            return self.Width * self.Length
    
        @classmethod
        def tell_info(cls,x):
            print(cls)
            print('--->>',cls.tag,x)
    
    Room.tell_info(10)

    1.3静态方法

    静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,主要是一些逻辑属于类,但是和类本身没有交互,即在静态方法中,不会涉及到类中的方法和属性的操作。可以理解为将静态方法存在此类的名称空间中。事实上,在python引入静态方法之前,通常是在全局名称空间中创建函数。

    例如:

    class Room:
        tag = 1
    
        def __init__(self, name, owner, width, length, heigth):
            self.Name = name
            self.Owner = owner
            self.Width = width
            self.Length = length
            self.Heigth = heigth
    
        def cal_area(self):
            return self.Width * self.Length
        @staticmethod
        def bathroom(a,b,c):
            print('%s %s %s正在洗澡' %(a,b,c))
    
    Room.bathroom('老赵','老李','老孔')
    
    r1=Room('客厅','czd',10,10,3)
    r1.bathroom('老赵','老李','老孔')

    二、python之组合

    2.1组合

    组合就是一个类中使用到另一个类,从而把几个类拼到一起。组合的功能也是为了减少重复代码。

    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('福州大学','旗山校区')
    s2=School('福州大学','晋江校区')
    s3=School('福州大学','厦门校区')
    
    c1=Course('物流',8000,'1year',s1)
    
    msg='''
        1    福州大学   旗山校区
        2    福州大学   晋江校区
        3    福州大学   厦门校区
        '''
    while True:
        print(msg)
        menu={
            '1':s1,
            '2':s2,
            '3':s3
        }
    
        choice=input('选择学校>>:')
        school_obj=menu[choice]
    
        name=input('课程名>>:')
        price=input('课程费用》:')
        period=input('课程周期>>:')
        new_course=Course(name,price,period,school_obj)
        print('课程%s属于%s学校' %(new_course.name,new_course.school.name))
    View Code

    三、继承

    3.1继承

    面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。

    3.2何时使用继承

    假如我需要定义几个类,而类与类之间有一些公共的属性和方法,这时我就可以把相同的属性和方法作为基类的成员,而特殊的方法及属性则在本类中定义,这样只需要继承基类这个动作,就可以访问到基类的属性和方法了,它提高了代码的可扩展性。

    3.3继承的特点

    1:在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。有别于C#

    2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数

    3:Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。

    3.4继承的顺序

    class A:
        def test(self):
            print(A)
    
    class B(A):
        def test(self):
            print(B)
    
    class C(A):
        def test(self):
            print(C)
    
    class D(B):
        def test(self):
            print(D)
    
    class E(C):
        def test(self):
            print(E)
    
    class F(D,E):
        def test(self):
            print(F)
    
    
    f1=F()
    f1.test()     #新式类顺序 F-->D-->B-->E-->C-->A
    
    print(F.__mro__)

    3.5接口继承

    接口继承就是(基类)父类定义好2个函数属性(接口),所有的子类必须有这2个函数属性,缺一不可,不是说省代码的,是用来做强制性约束的接口继承。

    基类里面的方法不用具体的实现,只是一个规范而已。例如:

    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()
    View Code

    四、补充

    4.1子类中调用父类

    class Vehicle:
        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('开动啦')
            print('开动啦')
            print('开动啦')
            print('开动啦')
    
    class Subway(Vehicle):
        def __init__(self,name,speed,load,power,line):
            Vehicle.__init__(self,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)
            print("%s %s 线,开动啦" %(self.name,self.line))
    
    line1=Subway('兰州地铁','100m/s',1000,'',1)
    
    line1.show_info()
    line1.run()

    利用Super方法调用:

    #Super方法
    class Vehicle:
        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('开动啦')
            print('开动啦')
            print('开动啦')
            print('开动啦')
    
    class Subway(Vehicle):
        def __init__(self,name,speed,load,power,line):
            super().__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):
            super().run()
            print("%s %s 线,开动啦" %(self.name,self.line))
    
    line1=Subway('兰州地铁','100m/s',1000,'',1)
    
    line1.show_info()
    line1.run()
    View Code

     

     

  • 相关阅读:
    mvc
    拦截器
    使用HttpWebRequest和HtmlAgilityPack抓取网页(拒绝乱码,拒绝正则表达式)
    编译和解释的区别是什么?
    15 个最佳的 jQuery 表格插件
    编程小白必备——主流语言C语言知识点
    妹子找你修电脑,按照这几步操作,你就是黑客大佬!
    网络管理监视很重要!学编程的你知道哪些不错的网络监控工具?2020 最好的Linux网络监控工具分享给你
    为什么程序员要跳槽,钱并非第一位
    代码编写行为准则,编码是一个认真思考的过程,如何有效提高代码的可读性?
  • 原文地址:https://www.cnblogs.com/changzhendong/p/11307982.html
Copyright © 2011-2022 走看看