zoukankan      html  css  js  c++  java
  • 静态方法、类方法、属性方法、类的特殊成员方法

    一、静态方法

    1、定义

    在方法名前加上@staticmethod装饰器,表示此方法为静态方法

    class Dog(object):
        def __init__(self,name):
            self.name = name
        @staticmethod    #在方法前加上staticmethod 装饰器定义静态方法
        def eat():
            print("the dog like eat bone")
        
    

    2、静态方法特性

     特性:只是名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性

    (1)静态方法不可以传入self参数,如果想传调用时必须传入实例本身 

    class Dog(object):
        def __init__(self,name):
            self.name = name
        @staticmethod    #在方法前加上staticmethod 装饰器定义静态方法
        def eat(self,food): #可以定义,但是需传入实例本身
            print("{0} like eat {1}".format(self.name,food))
    d=Dog("Mike")
    d.eat(d,"bone")#传入实例d本身,否则会报错
    # 结果
    Mike like eat bone
    

     (2)静态方法可以用类直接调用,直接调用时,不可以直接传入self,否则会报错

    class Dog(object):
        def __init__(self,name):
            self.name = name
        @staticmethod    #在方法前加上staticmethod 装饰器定义静态方法
        def eat(food): 
            print("Mike like eat {0}".format(food))
    
    Dog.eat("bone")
    #结果
    Mike like eat bone
    

      (3)应用场景

    一般情况下我们需要使用工具包的一些个类的封装,可以用静态方法,比如os模块

    import os
    os.system()
    os.mkdir()
    

      上面两个方法没有什么必然的联系在里面,所以可以这么用

    二、类方法

    1、定义

    在方法名前加上@classmethod装饰器,表示此方法为类方法

    class Dog(object):
        name="Mike"
        def __init__(self,name):
            self.name = name
        @classmethod    #定义类方法
        def eat(self,food):
            print("{0} like eat {0}".format(self.name,food))
    

    2、类方法特性

    特性:只能访问类变量(又叫静态属性),不能访问实例变量

    (1)访问实例变量

    class Dog(object):
        def __init__(self,name):
            self.name = name
        @classmethod    #定义类方法
        def eat(self,food):
            print("{0} like eat {1}".format(self.name,food))
    
    d=Dog("Mike")
    d.eat("bone")
    #结果
    Traceback (most recent call last):
      File "/Users/bianbian/PycharmProjects/test/ha.py", line 9, in <module>
        d.eat("bone")
      File "/Users/bianbian/PycharmProjects/test/ha.py", line 6, in eat
        print("{0} like eat {1}".format(self.name,food))
    AttributeError: type object 'Dog' has no attribute 'name'
    

     (2)访问类变量(又叫静态属性)

    class Dog(object):
        name = "Coco"
        def __init__(self,name):
            self.name = name
        @classmethod    #定义类方法
        def eat(self,food):
            print("{0} like eat {1}".format(self.name,food))
    
    d=Dog("Mike")
    d.eat("bone")
    #结果
    Coco like eat bone
    

      三、属性方法

    1、定义

    在方法名前加上@property装饰器,表示此方法为属性方法

    class Dog(object):
        def __init__(self,name):
            self.name = name
        @property    #定义属性方法
        def eat(self):
            return self.name
    
    
    d = Dog("Mike")
    print(d.eat)
    #结果
    Mike
    

    2、特性

    class Dog(object):
        def __init__(self,name):
            self.name = name
        @property    #定义属性方法
        def eat(self):
            print("{0} is eating".format(self.name))
    
    
    d = Dog("Mike")
    d.eat  #把方法变成静态属性调用
    #结果
    Mike is eating

      如何传入参数??

    (1)给转换后的静态属性赋值

    用@静态方法名.setter去装饰方法,来给转换后的静态属性赋值

    class Dog(object):
        def __init__(self,name):
            self.name = name
        @property    #定义属性方法
        def eat(self):
            print("{0} is eating {1}".format(self.name,"bone"))
        @eat.setter
        def eat(self,food):
            print("set food:",food)
    d = Dog("Mike")
    d.eat="hotdog" #给转成的静态变量赋值
    d.eat
    #结果
    set food: hotdog
    Mike is eating bone #并没有把设置的food传给eat
    

      上述方法不可行

    class Dog(object):
        def __init__(self,name):
            self.name = name
            self.__food = None
        @property    #定义属性方法
        def eat(self):
            print("{0} is eating {1}".format(self.name,self.__food))
        @eat.setter
        def eat(self,food):
            print("set food:",food)
            self.__food = food
    d = Dog("Mike")
    d.eat   #第一次赋值的是None
    d.eat = "hotdog" #给转成的静态变量赋值
    d.eat    #第二次赋值是hotdog
    #结果
    Mike is eating None
    set food: hotdog
    Mike is eating hotdog
    

    (2)删除转变的静态属性

    用@静态方法名.deleter去装饰,表明可以删除转化后的静态属性

    class Dog(object):
        def __init__(self,name):
            self.name = name
            self.__food = None
        @property    #定义属性方法
        def eat(self):
            print("{0} is eating {1}".format(self.name,self.__food))
        @eat.setter
        def eat(self,food):
            print("set food:",food)
            self.__food = food
        @eat.deleter   #定义可以删除eat这个静态属性
        def eat(self):
            del self.__food
            print("food变量删除完毕")
    d = Dog("Mike")
    d.eat   #第一次赋值的是None
    d.eat = "hotdog" #给转成的静态变量赋值
    d.eat    #第二次赋值是hotdog
    del d.eat
    #结果
    Mike is eating None
    set food: hotdog
    Mike is eating hotdog
    food变量删除完毕
    

    3、练习

    想知道一个火车车次当前的状态,是到达了、晚点了、取消了、还是已经开走了,需要做下面几件事:

    (1) 连接12306的API查询

    (2)对查询结果进行解析 

    (3)返回结果给用户

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

    class Train(object):
        def __init__(self,name):
            self.train_name = name
        def checking_status(self):
            print("Checking the train is %s" %self.train_name)
            return 1
        @property
        def train_status(self):
            status = self.checking_status()
            if status == 0:
                print("The train has canceled")
            elif status == 1:
                print("The train has arrived")
            elif status == 2:
                print("The train has drived away")
            else:
                print("Sorry,cannot confirm the train status,please check later")
        @train_status.setter
        def train_status(self,status):
            status_dic={
                0:"canceled",
                1:"arrived",
                2:"drived away"
            }
            print("33[31;1mHas changed the flight status to 33[0m",status_dic.get(status))
        @train_status.deleter
        def train_status(self):
            print("The status has been removed")
    T = Train("D007")
    T.train_status
    T.train_status = 2
    del T.train_status  

    结果

    Checking the train is D007
    The train has arrived
    Has changed the flight status to  drived away
    The status has been removed
    

     四、类的特殊成员方法

    1、__doc__

    表示类的描述信息

    class Dog(object):
        """此类是形容Dog这个类"""  # 类的描述信息
        def __init__(self,name):
            self.name = name
    print(Dog.__doc__)
    #结果
    此类是形容Dog这个类

    2、__module__和__class__

    __module__: 表示当前操作的对象在哪个模块

    __class__:表示当前操作的对象的类是什么

    cc.py里面的内容

    class Dog(object):
        def __init__(self):
            self.name = "Mike"
    

    21123.py里面的内容

    from lib.cc import Dog
    obj = Dog()
    print(obj.__module__) #表示当前操作的对象在哪个模块
    print(obj.__class__)  #表示当前操作的对象的类是什么
    

     运行21123.py,结果:

    lib.cc
    <class 'lib.cc.Dog'>

    3、__init__

    构造方法,通过类创建对象时,自动触发执行

    4、__del__

    析构方法,当对象在内存中被释放时,自动触发执行

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,

    所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的

    5、__call__

    对象后面加括号,触发执行

    class Dog(object):
        def __init__(self):
            self.name = "Mike"
        def __call__(self, *args, **kwargs): #重写call方法
            print("重写call方法",args,kwargs)
    D = Dog()  #执行__init__
    D(1,2,3,4,name="Coco")  # 执行call方法,也可以写成 Dog()(1,2,3,4,name="Coco")
    #结果
    重写call方法 (1, 2, 3, 4) {'name': 'Coco'}  

    构造方法的执行是由创建对象触发的,即:对象 = 类名() ;

    而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    6、__dict__

    查看类或对象中的所有成员

    (1)类.__dict__

    效果:打印类中所有的属性,不包括实例属性

    class Dog(object):
        name = "Coco"
        def __init__(self,food):
            self.name = name
            self.food =food
        def food(self, *args, **kwargs):
            print("food",args,kwargs)
    print(Dog.__dict__)
    #结果
    {'__module__': '__main__', 'name': 'Coco', '__init__': <function Dog.__init__ at 0x102ab5ea0>, 'food': <function Dog.food at 0x102ab5d90>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}
    

     (2)实例名.__dict__

    效果:打印该实例的所有属性,不包括类属性

    class Dog(object):
        name = "Coco"
        def __init__(self,name,food):
            self.name = name
            self.food =food
        def food(self, *args, **kwargs):
            print("food",args,kwargs)
    d = Dog("Mike","Bone")
    print(d.__dict__)
    #结果
    {'name': 'Mike', 'food': 'Bone'} #打印该实例的所有属性,不包括类属性
    

    7、__str__

    如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值

    class Dog(object):
        name = "Coco"
        def __init__(self,name):
            self.name = name
        def __str__(self):
            return "obj:{0}".format(self.name)
    d = Dog("Mike")
    print(d)
    #结果
    obj:Mike

    8、 __getitem__、__setitem__、__delitem__

    用于索引操作,如字典。以上分别表示获取、设置、删除数据

    class Dog(object):
        def __getitem__(self,key):
            print('__gettem__:',key)
    
        def __setitem__(self, key,value):
            print('__settem__:',key)
        def __delitem__(self,key):
            print('__delitem__:',key)
    
    d = Dog()
    d["name"]="mike" #自动触发__setitem__方法
    d["name"]   #自动触发__getitem__方法
    
    del d["name"]        # 自动触发__delitem__方法
    #结果
    __settem__: name
    __gettem__: name
    __delitem__: name
    

    __delitem__没有做真正的删除,只是触发这个方法,想要真正删除,只需要在__delitem__函数中添加删除功能即可

    五、总结

    1. 静态方法访问不了类或实例中的任何属性,它已经脱离了类,一般会用在一些工具包中
    2. 类方法,只能访问类变量,不能访问实例变量
    3. 属性方法是把一个方法变成一个静态属性

      

  • 相关阅读:
    scp 利用 ssh 协议 复制文件
    linux (fedora 28) 制作启动U盘,启动盘
    nc 命令使用详解
    env :让系统决定你命令的位置
    tali -f 和 tail -F 之间的区别
    斯诺克台球比赛规则 (Snooker)
    中式台球 规则 ( ChinaBilliards )
    美式九球比赛规则 (Nine-ball)
    Tmux 使用教程 on Fedora 28
    python 3.6 的 venv 模块
  • 原文地址:https://www.cnblogs.com/bianfengjie/p/10858403.html
Copyright © 2011-2022 走看看