Day28_property_staticmethod_classmethod用法

一. 上节课复习

  1. 多态与多态性

二.property

  1. 什么是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
    '''
    
  2. property的设置、删除

    class Foo:
    def __init__(self,val):
        self.__NAME=val #将所有的数据属性都隐藏起来
    
    @property
    def name(self):
        return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)
    
    @name.setter
    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):
        del self.__NAME
    
    f=Foo('egon')
    print(f.name)
    # f.name=10 #抛出异常'TypeError: 10 must be str'
    del f.name
    print(f.name)   #'Foo' object has no attribute '_Foo__NAME'
    
  3. 被property装饰的属性会优先于对象的属性被使用,而被property装饰的属性,如sex,分成三种:

    class People:
    def __init__(self,name,SEX):
        self.name = name
        self.sex = SEX          #设置sex 会调用property下的setter
    
    @property
    def sex(self):
        print('from property')
        return self.__sex
    
    @sex.setter
    def sex(self,value):
        print('from setter')
        self.__sex = value
    
    @sex.deleter
    def sex(self):
        print('from deleter')
        del self.__sex
    
    p1 = People('Lex','male')       #from setter
    
    print(p1.__dict__)              #{'name': 'Lex', '_People__sex': 'male'}
    print(p1.sex)                   #from property
                                    #male
    del p1.sex                      #from deleter
    print(p1.__dict__)              #{'name': 'Lex'}
    
    1. property
    2. sex.setter
    3. sex.deleter

三. staticmethod

  1. 非绑定方法
    在类内部用staticmethod装饰的函数即非绑定方法,就是普通函数,statimethod不与类或对象绑定,谁都可以调用,没有自动传值效果
    import time  
    
    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()    #获取结构化的时间格式
            obj = Date(t.tm_year,t.tm_mon,t.tm_mday)    #新建实例并且返回
            return obj  
            
        @staticmethod
        def tomorrow(): #用Date.tomorrow()形式去产生实例,该用例用的是明天的时间
            t = time.localtime(time.time()+86400)
            obj = Date(t.tm_year,t.tm_mon,t.tm_mday)
            return obj
                
    d1 = Date.now()
    print(d1.year,d1.month,d1.day)
    d2 = Date.tomorrow()
    print(d2.year,d2.month,d2.day)
    #注意:  
    #1. 如果不加staticmethod:但凡是定义在类的内部,并且没有被任何装饰器装饰过的方法,都是绑定方法,有自动传值的功能  
    d1.now()        #报错,TypeError: now() takes 0 positional arguments but 1 was given
    #2. 如果增加staticmethod:但凡是定义在类的内部,并且被staticmethod装饰器修饰过的方法,都是解除绑定的方法,实际上就是函数,没有自动传值的功能  
    d1 = Date(2012,12,12)
    d_n1 = Date.now()
    d_n2 = d1.now()    与上面相等
    print(d_n1.year,d_n1.month,d_n1.day)
    print(d_n2.year,d_n2.month,d_n2.day)
    

四.classmethod

  1. classmethod的基本使用

    class FOO:
        def bar(self):
            pass
    
        @classmethod    #把一个方法绑定给类:类.绑定到类的方法(),会把类本身当做第一个参数自动传给绑定到类的方法
        def test(cls,x):
            print(cls,x)    #拿掉一个类的内存地址后,就可以实例化或者引用类的属性了
    
    f = FOO()
    print(f.bar)        #<bound method FOO.bar of <__main__.FOO object at 0x000000000269B208>>    对象的绑定方法
    print(f.test)       #<bound method FOO.test of <class '__main__.FOO'>>                        类的绑定方法
    print(FOO.test)     #<bound method FOO.test of <class '__main__.FOO'>>                        类的绑定方法
    
    f.test(111)         #<class '__main__.FOO'> 111,实例可以调用,但是第一个参数传入的是实例对应的类
    FOO.test(111)       #<class '__main__.FOO'> 111
    
  2. 类中函数不加任何装饰器:为foo2的对象

    class foo:
        def foo1(self):
            pass
    
    class foo2(foo):
        pass
    
    f1 = foo2()
    print(f1)       #<__main__.foo2 object at 0x00000000026C89B0>
    
  3. 类中函数增加装饰器staticmethod:为Date的对象,且不会触发__str__

    import time
    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()    #获取结构化的时间格式
            obj = Date(t.tm_year,t.tm_mon,t.tm_mday)    #新建实例并且返回
            return obj
    
    class EuroDate(Date):
        def __str__(self):
            return '<name:%s,age:%s>' % (self.name, self.age)
    
    e1 = EuroDate.now()
    print(e1)           #<__main__.Date object at 0x0000000001E8B320>,
    
  4. 类中函数增加装饰器classmethod:为EuroDate的对象,触发__str__

    import time
    class Date:
        def __init__(self,year,month,day):
            self.year = year
            self.month = month
            self.day = day
    
        @classmethod
        def now(cls):
            t = time.localtime()    #获取结构化的时间格式
            obj = cls(t.tm_year,t.tm_mon,t.tm_mday)    #新建实例并且返回
            return obj
    
    class EuroDate(Date):
        def __str__(self):
            return '<year:%s,mont:%s,day:%s>'%(self.year,self.month,self.day)       
    
    e1 = EuroDate.now()
    print(e1)           #<year:2017,mont:11,day:19>
                        # #<__main__.Date object at 0x0000000001E8B320>
    

五. __str__的用法

  1. __str__定义在类的内部,必须返回一个字符串类型
  2. 打印由这个类产生的对象时 ,会触发执行
    class foo:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __str__(self):
            return '<name:%s,age:%s>'%(self.name,self.age)
    
    f1 = foo('lex',18)
    print(f1)           #<name:lex,age:18>
    
原文地址:https://www.cnblogs.com/sama/p/7864946.html