5、第六 - 面向对象高级语法-静态方法、类方法、属性方法
静态方法:
     只是名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性。
类方法:
	  只能访问类变量,不能访问实例变量。
属性方法:
	  把一个方法变成一个静态属性;隐藏实现细节。
通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法。其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self. 调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法。
举例如下:
1、正常情况下:
class Dog(object):
    def __init__(self,name):
        self.name = name
    def eat(self):
        print("%s is eating" % self.name)
d = Dog("Dog1")
d.eat()
输出:
Dog1 is eating
2、添加静态方法后:
class Dog(object):
    def __init__(self,name):
        self.name = name
    @staticmethod #实际上跟class类没有关系的一个函数糊,名义归类管。
    def eat(self):
        print("%s is eating" % self.name)
d = Dog("Dog1")
d.eat()
输出报错信息:
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/mac/PycharmProjects/untitled2/51CTO/6day/静态方法1.py
Traceback (most recent call last):
  File "/Users/mac/PycharmProjects/untitled2/51CTO/6day/静态方法1.py", line 10, in <module>
    d.eat()
TypeError: eat() missing 1 required positional argument: 'self'
添加@staticmethod 静态方法后,上面的调用出现了错误,说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。
让上面的代码可以正常工作有两种办法:
1. 调用时主动传递实例本身给eat方法,即d.eat(d) 
2. 在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了
第一种方法:
class Dog(object):
    def __init__(self,name):
        self.name = name
    @staticmethod
    def eat(self):
        print("%s is eating" % self.name)
d = Dog("Dog1")
d.eat(d)  #调用时主动传递实例本身给eat方法,即d.eat(d)
输出:
Dog1 is eating
第二种方法:
class Dog(object):
    def __init__(self,name):
        self.name = name
    @staticmethod
    def eat(name): #更改这个位置,把self 去掉,就回到之前的函数传参调用的方法
        print("%s is eating" % name)
d = Dog("123") #随意传个参数,def __init__(self,name):中需要用到。
d.eat("Dog1") #eat函数不会调用self.name,eat函数已独立出来,需要单独传参
输出:
Dog1 is eating
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
正常情况下:
class Dog(object):
    def __init__(self,name):
        self.name = name
    def eat(self):
        print("%s is eating" % self.name)
d = Dog("Dog1")
d.eat()
输出:
Dog1 is eating
添加类方法后:
class Dog(object):
    def __init__(self,name):
        self.name = name
    @classmethod
    def eat(self):
        print("%s is eating" % self.name)
d = Dog("Dog1")
d.eat()
输出报错信息:
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/mac/PycharmProjects/untitled2/51CTO/6day/静态方法1.py
Traceback (most recent call last):
  File "/Users/mac/PycharmProjects/untitled2/51CTO/6day/静态方法1.py", line 11, in <module>
    d.eat()
  File "/Users/mac/PycharmProjects/untitled2/51CTO/6day/静态方法1.py", line 8, in eat
    print("%s is eating" % self.name)
AttributeError: type object 'Dog' has no attribute 'name'
说Dog没有name属性,因为name是个实例变量,类方法是不能访问实例变量的。
让上面的代码可以正常工作的办法:可以定义一个类变量,也叫name。如下
class Dog(object):
    name = "Dog2"
    def __init__(self,name):
        self.name = name
    @classmethod
    def eat(self):
        print("%s is eating" % self.name)
d = Dog("Dog1")
d.eat()
输出:
Dog2 is eating   
注意:添加类方法后,eat(self)调用了name = "Dog2"变量,类方法不能调用self.name 所以输出的为Dog2
属性方法的作用就是通过@property把一个方法变成一个静态属性
正常情况下:
class Dog(object):
    def __init__(self,name):
        self.name = name
    def eat(self):
        print("%s is eating" % self.name)
d = Dog("Dog1")
d.eat()
输出:
Dog1 is eating
添加属性方法:
class Dog(object):
    def __init__(self,name):
        self.name = name
    @property
    def eat(self):
        print("%s is eating" % self.name)
d = Dog("Dog1")
d.eat()
输出报错信息:
Dog1 is eating
Traceback (most recent call last):
  File "/Users/mac/PycharmProjects/untitled2/51CTO/6day/静态方法1.py", line 10, in <module>
    d.eat()
TypeError: 'NoneType' object is not callable
调用会出以下错误, 说NoneType is not callable, 因为eat此时已经变成一个静态属性了, 不是方法了, 想调用已经不需要加()号了,直接d.eat就可以了
class Dog(object):
    def __init__(self,name):
        self.name = name
    @property  #def eat  函数为静态属性
    def eat(self):
        print("%s is eating" % self.name)
d = Dog("Dog1")
d.eat  #直接调用
输出:
Dog1 is eating
属性方法的应用场景,举例:
想知道一个航班当前的状态,是到达了、延迟了、取消了、还是已经飞走了, 想知道这种状态。
经历以下几步:
1. 连接航空公司API查询
2. 对查询结果进行解析 
3. 返回结果给你的用户
status属性的值是一系列动作后才得到的结果,所以你每次调用时,其实它都要经过一系列的动作才返回你结果,但这些动作过程不需要用户关心, 用户只需要调用这个属性就可以。
class Flight(object):
    def __init__(self,name):
        self.name = name
    def checking_status(self):
        print("checking flight %s status" % self.name)
        return 0
    @property
    def flight_status(self):
   
        status = self.checking_status()#定义静态变量,checking_status()根据return的返回值,进行判断
        
        if status == 0:
            print("flight got canceled...")
        elif status == 1:
            print("flight is arrived...")
        elif status == 2:
            print("flight has departured already...")
        else:
            print("cannot confirm the flight status...,please check later")
f = Flight("CA988")
f.flight_status 
输出:
checking flight CA988 status
flight got canceled...
flight_status既然已经是个属性,调用赋值的时候,就会报错:
class Flight(object):
    def __init__(self,name):
        self.name = name
    def checking_status(self):
        print("checking flight %s status" % self.name)
        return 0
    @property
    def flight_status(self):
        status = self.checking_status()#定义静态变量,checking_status()根据return的返回值,进行判断
        if status == 0:
            print("flight got canceled...")
        elif status == 1:
            print("flight is arrived...")
        elif status == 2:
            print("flight has departured already...")
        else:
            print("cannot confirm the flight status...,please check later")
f = Flight("CA988")
f.flight_status = 2  #调用赋值
输出摆错信息:
Traceback (most recent call last):
  File "/Users/mac/PycharmProjects/untitled2/51CTO/6day/静态方法1.py", line 24, in <module>
    f.flight_status = 2 
AttributeError: can't set attribute
提示不能更改这个属性
如何可以调用的时候,正常赋值。需要添加@proerty.setter装饰器再装饰一下
class Flight(object):
    def __init__(self,name):
        self.name = name
    def checking_status(self):
        print("checking flight %s status" % self.name)
        return 0
    @property
    def flight_status(self):
        status = self.checking_status()#定义静态变量,checking_status()根据return的返回值,进行判断
        if status == 0:
            print("flight got canceled...")
        elif status == 1:
            print("flight is arrived...")
        elif status == 2:
            print("flight has departured already...")
        else:
            print("cannot confirm the flight status...,please check later")
    @flight_status.setter #修改,相当于重新定义了一个函数
    def flight_status(self,status):
        status_dic = {
            0 : "canceled",
            1 : "arrived",
            2 : "departured"
        }
        print("\033[31;1mHas changed the flight status to \033[0m",status_dic.get(status) )
    @flight_status.deleter  #删除
    def flight_status(self):
        print("status got removed...")
f = Flight("CA988")
f.flight_status = 2 #触发@flight_status.setter
del f.flight_status #触发@flight_status.deleter 
输出:
Has changed the flight status to  departured
status got removed...
备注:@flight_status.deleter, 是允许可以将这个属性删除
                    
                
                
            
        
浙公网安备 33010602011771号