• 面向对象之静态属性与绑定方法


    静态方法

    什么是特性property:

    property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

    圆的周长和面积:
    import math
    class Circle:
        def __init__(self,radius): #圆的半径radius
            self.radius=radius
    
        @property
        def area(self):
            return math.pi * self.radius**2 #计算面积
    
        @property
        def perimeter(self):
            return 2*math.pi*self.radius #计算周长
    
    c=Circle(10)
    print(c.radius)
    print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
    print(c.perimeter) #同上
    '''
    输出结果:
    314.1592653589793
    62.83185307179586
    '''
    

    注意:此时的特性area和perimeter不能被赋值

    	c.area=3 #为特性area赋值
    	'''
    	抛出异常:
    	AttributeError: can't set attribute
    	'''
    
    为什么要用property

    将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

    除此之外,看下:

    ps:面向对象的封装有三种方式:
    【public】
    这种其实就是不封装,是对外公开的
    【protected】
    这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
    【private】
    这种封装对谁都不公开
    

    python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现

    class Foo:
        def __init__(self,val):
            self.__NAME=val #将所有的数据属性都隐藏起来
    
        @property
        def name(self):
            return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)
    
        @name.setter  #可以对property的属性方法设置,首先进行了检验,保证了设置的值为int类型
        def name(self,value):
            if not isinstance(value,str):  #在设定值之前进行类型检查
                raise TypeError('%s must be str' %value)
            self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME
    
        @name.deleter # 定义不能删除静态属性,抛出异常
        def name(self):
            raise TypeError('Can not delete')
    
    f=Foo('egon')
    print(f.name)
    # f.name=10 #抛出异常'TypeError: 10 must be str'
    del f.name #抛出异常'TypeError: Can not delete'
    

    一 类中定义的方法分为两类:

    绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入)

    1.绑定到类的方法:用classmethod装饰器装饰的方法。为类量身定制.

    类.boud_method(),自动将类当作第一个参数传入,(其实对象也可调用,但仍将类当作第一个参数传入)。

    2. 绑定到对象的方法:没有被任何装饰器装饰的方法:

    为对象量身定制

    对象.boud_method(),自动将对象当作第一个参数传入(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)

    二:非绑定方法:用staticmethod装饰器装饰的方法:

    1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说,就是一个普通工具而已.

    注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

    绑定给类的方法(classmethod)

    classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数(即便是对象来调用也会将类当作第一个参数传入),python为我们内置了函数classmethod来把类中的函数定义成类方法.

    	class Room():
    	    name = "房子"
    	
    	    def __init__(self, name, type, width, lenth, hight):
    	        self.name = name
    	        self.type = type
    	        self.width = width
    	        self.lenth = lenth
    	        self.hight = hight
    	
    	    @property  #静态方法
    	    def cal_area(self):
    	        return self.width * self.lenth
    	
    	    def cal_volume(self):
    	        return self.width * self.hight * self.lenth
    	
    	    @classmethod #类方法
    	    def tell_info(cls):
    	        print("类得属性", cls.name, )
    	        print(cls)# cls.hight  这个是实例的数据属性 类方法调用不到
    	
    
    	r1 = Room("alex", "厕所", 100, 100, 1000)
    	# print(r1.cal_area)
    	
    	print(r1.tell_info())  # 实例 方法也可以调用类方法 毕竟实例本身没有方法
    	
    	# print(Room.tell_info())  # 类调用方法,并且把类本身的数据属性传递给类方法
    

    三 非绑定方法

    在类内部用staticmethod装饰的函数即非绑定方法(类的工具包),就是普通函数,statimethod不与类或对象绑定,谁都可以调用,没有自动传值效果。

    class Room():
    def __init__(self, name, type, width, lenth, hight):
        self.name = name
        self.type = type
        self.width = width
        self.lenth = lenth
        self.hight = hight
    
    @property 
    def cal_area(self):
        return self.width * self.lenth
    
    def cal_volume(self):
        return self.width * self.hight * self.lenth
    
    @staticmethod  
    def test():
        print("我是静态方法,是类得工具包")  #不能访问类得属性与实例属性
    
    def NOT_test():
        print("我不是静态方法,如果实例调用我 类会自动给实例传递一个参数")
    
    
    r1 = Room("alex", "厕所", 100, 100, 1000)
    
    print(r1.cal_area)
    
    r1.test()
    print(r1.test)  # <function Room.test at 0x00000000011A7840> 普通函数
    # r1.NOT_test()   #会报错因为这个实例的类直接把自己自动传给了这个Ttest方法,导致传递多了参数
    Room.NOT_test()  # 这个不会报错因为累调用自己的方法  不会把自己传进去
    

    四 classmethod与staticmethod的对比 :

    import settings
    class MySQL:
        def __init__(self,host,port):
            self.host=host
            self.port=port
    
        @staticmethod
        def from_conf():
            return MySQL(settings.HOST,settings.PORT)
    
        # @classmethod #哪个类来调用,就将哪个类当做第一个参数传入
        # def from_conf(cls):
        #     return cls(settings.HOST,settings.PORT)
    
        def __str__(self):
            return '就不告诉你'
    
    class Mariadb(MySQL):
        def __str__(self):
            return '<%s:%s>' %(self.host,self.port)
    
    
    m=Mariadb.from_conf()
    print(m) #我们的意图是想触发Mariadb.__str__,但是结果触发了MySQL.__str__的执行,打印就不告诉你:
  • 相关阅读:
    Python修饰符实践
    回文
    Linux下安装Qt
    Linux下安装PyQT
    Python闭包实践
    杂乱
    windows下脚本转到linux下,文件保存格式要转换
    lua table.sort的bug
    shell截取某段
    coredump
  • 原文地址:https://www.cnblogs.com/zjcode/p/8693968.html
Copyright © 2020-2023  润新知