zoukankan      html  css  js  c++  java
  • 静态方法、类方法、属性方法

    一、静态方法

     1.1、定义

       在类中的方法前面通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法

    class Person(object):
    
        def __init__(self, name):
            self.name = name
    
        @staticmethod
        def speak():
            print('someone is speaking chinese.')
    
    # 静态方法在类中也不需要传入 self参数
    

      

    1.2、静态方法的特性

      静态方法是不能访问实例变量和类变量的 

    class Person(object):
    
        def __init__(self, name):
            self.name = name
    
        @staticmethod
        def speak(self):
            print('%s is speaking chinese.' % self.name)
    
    p = Person('Bigberg')
    p.speak()
    
    
    # 我们在 speak(self) 函数中传入 self
    

      事实上以上代码运行会出错的,说speak 需要一个self参数,但调用时却没有传递,没错,当speak变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。  

    Traceback (most recent call last):
      File "G:/python/untitled/study6/静态方法.py", line 26, in <module>
        p.speak()
    TypeError: speak() missing 1 required positional argument: 'self'
    

      想让以上代码可以正常执行,有两种方法:

    1. 在调用时将实例本身传给 speak() 
    class Person(object):
    
        def __init__(self, name):
            self.name = name
    
        @staticmethod
        def speak(self):
            print('%s is speaking chinese.' % self.name)
    
    p = Person('Bigberg')
    p.speak(p)
    
    # 输出
    
    Bigberg is speaking chinese.
    

      2.在方法speak中去掉self,但这也意味着,在eat中不能通过self.调用实例中的其它变量了 

    class Person(object):
    
        def __init__(self, name):
            self.name = name
    
        @staticmethod
        def speak():                # 方法中已经没有 self 参数了
            print('%s is speaking chinese.' % 'anyone')
    
    p = Person('Bigberg')
    p.speak()
    
    
    #输出
    anyone is speaking chinese.
    

      

    1.3 总结

      普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法。

    二、类方法

      2.1、定义

      类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量

      2.2、访问实例变量

            直接访问实例变量会报错,没有该属性  

    class Person(object):
    
        def __init__(self, name, country):
            self.name = name
            self.country = country
    
        @classmethod
        def nationality(self):
            print('Bigberg is %s.' % self.country)
    
    p = Person('Bigberg', 'CN')
    p.nationality()
    
    # 输出
    Traceback (most recent call last):
      File "G:/python/untitled/study6/静态方法.py", line 31, in <module>
        p.nationality()
      File "G:/python/untitled/study6/静态方法.py", line 24, in nationality
        print('Bigberg is %s.' % self.country)
    AttributeError: type object 'Person' has no attribute 'country'
    
    # 提示没有一个 country 属性  

      2.3、访问类变量,即 全局属性/静态字段 

    class Person(object):
    
        country = 'Chinese'    # 增加一个 全局属性/静态字段
    
        def __init__(self, name, country):
    
            self.name = name
            self.country = country
    
        @classmethod
        def nationality(cls):    # 这里将sefl 改为 cls
            print('Bigberg is %s.' % cls.country)
    
    p = Person('Bigberg', 'CN')
    p.nationality()
    
    # 输出
    Bigberg is Chinese.
    

    三、属性方法 

       3.1、定义

      属性方法的作用就是通过@property把一个方法变成一个静态属性 

    class Person(object):
    
        country = 'Chinese'
    
        def __init__(self, name, country):
    
            self.name = name
            self.country = country
    
        @property
        def drive(self):
            print('%s is driving a car.' % self.name)
    
    p = Person('Bigberg', 'CN')
    p.drive()
    # 输出 
    Traceback (most recent call last): Bigberg is driving a car. File "G:/python/untitled/study6/静态方法.py", line 38, in <module> p.drive() TypeError: 'NoneType' object is not callable

      调用会出错误, 说NoneType is not callable, 因为eat此时已经变成一个静态属性了, 不是方法了, 想调用已经不需要加()号了,直接p.drive就可以了

      正常调用: 

    p = Person('Bigberg', 'CN')
    p.drive
    
    # 输出
    
    Bigberg is driving a car.
    

      

      3.2 setter用法

      如果我们想在属性方法里传参,比如车的品牌,我们就要用setter了,具体用法  @属性方法名.setter 

    class Person(object):
    
        country = 'Chinese'
    
        def __init__(self, name, country):
    
            self.name = name
            self.country = country
            self.car = "LAMBORGHINI"   # 定义车品牌为兰博基尼
    
        @property
        def drive(self):
            print('%s is driving a %s.' % (self.name, self.car))
    
    p = Person('Bigberg', 'CN')
    p.drive
    
    # 输出
    Bigberg is driving a LAMBORGHINI.
    

      很显然我们开出去的车就是兰博基尼,如果我们想自己传入车品牌呢?比如 特斯拉: 

    class Person(object):
    
        country = 'Chinese'
    
        def __init__(self, name, country):
    
            self.name = name
            self.country = country
            self.car = "LAMBORGHINI"   #当然这里也可以设置为私有属性
    
        @property
        def drive(self):  # 这里不能传参是因为调用的时候,p.drive 没有()了,不能传入
            print('%s is driving a %s.' % (self.name, self.car))
    
        @drive.setter     # 修饰方法drive,可以为属性赋值
        def drive(self, car):     # 我们要重新定义这个drive方法
            print("set car:", car)
            self.car = car
    
    p = Person('Bigberg', 'CN')
    p.drive = 'Tesla'     # 给属性赋值
    p.drive
    
    #输出
    
    set car: Tesla
    Bigberg is driving a Tesla.
    

      3.3 deleter 用法

      用来删除属性方法,具体用法 @属性方法名.deleter  

    # 以上例
    # 我们可以发现普通属性是可以通过del直接删除的
    # 比如
    print(p.name)
    del p.name
    print(p.name)
    
    # 输出
    
    Traceback (most recent call last):
    Bigberg
      File "G:/python/untitled/study6/静态方法.py", line 49, in <module>
        print(p.name)
    AttributeError: 'Person' object has no attribute 'name'
    
    #删除之后就不能再调用了
    

      但是我们用del p.drive这种方法来删除属性方法是行不通的:

    del p.drive
    
    #输出
    Traceback (most recent call last):
      File "G:/python/untitled/study6/静态方法.py", line 51, in <module>
        del p.drive
    AttributeError: can't delete attribute
    

      所以我们就要用到 deleter方法: 

    class Person(object):
    
        country = 'Chinese'
    
        def __init__(self, name, country):
    
            self.name = name
            self.country = country
            self.car = "LAMBORGHINI"
    
        @property
        def drive(self):
            print('%s is driving a %s.' % (self.name, self.car))
    
        @drive.setter
        def drive(self, car):
            print("set car:", car)
            self.car = car
    
        @drive.deleter   # 修饰 drive 方法,可以删除属性
        def drive(self):   # 重新定义 drive方法
            del self.car    #  删除的是属性
            print("扣了你的车,让你开豪车...")
    
    p.drive = 'Tesla'
    p.drive
    
    del p.drive   
    
    # 输出
    set car: Tesla
    Bigberg is driving a Tesla.
    扣了你的车,让你开豪车...
    

      让我们在秋名山再开一次车...

    p.drive
    
    # 输出
    扣了你的车,让你开豪车...
    Traceback (most recent call last):
      File "G:/python/untitled/study6/静态方法.py", line 57, in <module>
        p.drive
      File "G:/python/untitled/study6/静态方法.py", line 28, in drive
        print('%s is driving a %s.' % (self.name, self.car))
    AttributeError: 'Person' object has no attribute 'car'
    
    # 提示没有这个属性了
    

     

    四、属性方法应用场景

    你想知道一个航班当前的状态,是到达了、延迟了、取消了、还是已经飞走了, 想知道这种状态你必须经历以下几步:

    1. 连接航空公司API查询

    2. 对查询结果进行解析 

    3. 返回结果给你的用户

    因此这个status属性的值是一系列动作后才得到的结果,所以你每次调用时,其实它都要经过一系列的动作才返回你结果,但这些动作过程不需要用户关心,用户只要知道结果就行

    class Flight(object):
    
        def __init__(self, name):
            self.name = name
    
        def check_status(self):
            print("checking flight %s status" % self.name)
            return 1
    
        @property
        def flight_status(self):
            status = self.check_status()
            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")
    
        @flight_status.setter
        def flight_status(self, status):
            status_dic = {
                0: "canceled",
                1: "arrived",
                2: "departured"
            }
            print("33[31;1mHas changed the flight status to 33[0m", status_dic.get(status))
    
        @flight_status.deleter  # 删除
        def flight_status(self):
            print("status got removed...")
    
    f = Flight('CA980')
    f.flight_status 
    f.flight_status = 2
    
    #输出
    
    checking flight CA980 status
    flight is arrived...
    Has changed the flight status to  departured
    

      

    五、总结

    1.  静态方法是不可以访问实例变量或类变量的
    2. 类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
    3. 属性方法将一个方法变为类的属性,调用时不需要加()。有@property 、@属性方法名.setter、@属性方法名.deleter 三种装饰方法
  • 相关阅读:
    初认识AngularJS
    (imcomplete) UVa 10127 Ones
    UVa 10061 How many zero's and how many digits?
    UVa 11728 Alternate Task
    UVa 11490 Just Another Problem
    UVa 10673 Play with Floor and Ceil
    JSON对象和字符串的收发(JS客户端用typeof()进行判断非常重要)
    HTML.ActionLink 和 Url.Action 的区别
    EASYUI TREE得到当前节点数据的GETDATA方法
    jqueery easyui tree把已选中的节点数据拼成json或者数组(非常重要)
  • 原文地址:https://www.cnblogs.com/bigberg/p/7252349.html
Copyright © 2011-2022 走看看