欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

super,封装,类中的三个装饰器,反射

程序员文章站 2022-03-18 16:05:26
1.super ​ 【1】在py3中怎么用?在py2(新式类/经典类)中怎么用? ​ 【2】在单继承中执行父类的同名方法的时候怎么用? ​ 【3】super方法和mro方法的关系是什么? 2.封装: 3.类中的三个装饰器(内置函数) ​ 1.property ​ 2.classmethod ​ 3. ......
1.super

super,封装,类中的三个装饰器,反射

​ 【1】在py3中怎么用?在py2(新式类/经典类)中怎么用?

         -super是按照mro顺序来寻找当前类的下一个类。
    
         -在py3中不需要传参数,自动就帮我们寻找当前类的mro顺序的下一个类中的同名方法。super后()内默认传当前类的类名,当前类的对象。例:super(d,self).func()
        
         -在py2中的新式类中,需要我们主动传递参数super(子类的名字,子类的对象).函数名() ,这样才能够帮我们调用到这个子类的mro顺序的下一个类中的方法。
        
         -在py2的经典类中,并不支持使用super来找下一个类。

        #在多继承中遵循mro顺序:
        class a(object):
            def func(self):
                print('a')
        class b(a):
            def func(self):
                super().func()
                print('b')
        class c(a):
            def func(self):
                super().func()
                print('c')
        class d(b,c):
            def func(self):
                super().func()
                #或:
                # super(d,self).func()
                print('d')
        # 在d类中找super的func,那么可以这样写 super().func()
        # 也可以这样写 super(d,self).func() (并且在py2的新式类中必须这样写)

        d().func()    #super是按照mro顺序来寻找当前类的下一个类,查找顺序是dbca,找到a后开始执行a,执行完a再执行c,执行完c再执行b,执行完b再执行a。所以打印顺序与查找顺序相反
        # a
        # c
        # b
        # d

​ 【2】在单继承中执行父类的同名方法的时候怎么用?

        # 在单继承的程序中,super就是找父类,用来调用父类的同名方法时用 ,例如 super().__init__(name) 
        # 当方法名还有除了self以外的参数时,还要添加上这些参数。比如:name
        # 用super必须是在继承的前提下,class vipuser 继承 class user
        # 在单继承中 mro 就是一个一个父类的顺序。
        
    【记】场景:在单继承的程序中调用父类的同名方法时
        class user:
            def __init__(self,name):
                self.name = name
                
        class vipuser(user):
            def __init__(self,name,level,strat_date,end_date):

                # user.__init__(self,name)          # 主动传self和name,此方式可以不是继承,class vipuser不继承 class user
                super().__init__(name)              # 推荐的方式(源码中有单继承时多用这种方式),super后()内默认传当前类的类名,当前类的对象,只传 name 即可
                # super(vipuser,self).__init__(name) 

                self.level = level
                self.strat_date = strat_date
                self.end_date = end_date

        太白 = vipuser('太白',6,'2019-01-01','2020-01-01')
        print(太白.__dict__)#{'name': '太白', 'level': 6, 'strat_date': '2019-01-01', 'end_date': '2020-01-01'}

​ 【3】super方法和mro方法的关系是什么?

2.封装:
    1.概念:
    【1】 封装: 就是把属性或者方法装起来。   
    【2】广义上的封装:   把属性和方法装起来,外面不能直接调用了,要通过类的名字来调用。    
    【3】狭义上的封装:  把属性和方法藏起来,外面不能调用,只能在内部偷偷调用。


     2.使用私有的三种情况:私有的前提下是在类的内部
                (1)给一个名字前面加上了双下划线的时候,这个名字就变成了一个私有的。
                (2)所有的私有的内容或者名字都不能在类的外部调用,只能在类的内部使用了
                (3)所有的私有化都是为了让用户不在外部调用类中的某个名字
                (4)如果完成私有化 那么这个类的封装度就更高了。封装度越高,各种属性和方法的安全性也越高 但是代码越复杂。
            
            【1】不想让你看,也不想让你改。
   
                class user:
                    def __init__(self,name,passwd):
                        self.usr = name
                        self.__pwd = passwd  # 私有的实例变量/私有的对象属性
                alex = user('alex','sbsbsb')
                print(alex.__pwd)  # 报错 attributeerror: 'user' object has no attribute '__pwd'
                # print(alex.pwd)    # 报错  attributeerror: 'user' object has no attribute 'pwd'
        
            【2】可以让你看, 但不让你改。
                class user:
                    def __init__(self,name,passwd):
                        self.usr = name
                        self.__pwd = passwd  # 私有的实例变量/私有的对象属性
                        
                    def get_pwd(self):       # 表示的是用户不能改,只能看 通过 私有 + 某个get方法实现的
                        return self.__pwd
                
                alex = user('alex','sbsbsb')
                print(alex.get_pwd())#sbsbsb
        
           
            【3】可以看也可以改, 但是要求你按照我的规则改。
            class user:
                def __init__(self,name,passwd):
                    self.usr = name
                    self.__pwd = passwd  # 私有的实例变量/私有的对象属性
                def get_pwd(self):       # 表示的是用户不能改,只能看 通过 私有 + 某个get方法实现的
                    return self.__pwd
                def change_pwd(self):    # 表示用户必须调用我们自定义的修改方式来进行变量的修改 私有 + change方法实现
                    pass
            alex = user('alex','sbsbsb')
            print(alex.get_pwd())#sbsbsb
            
    3.封装的语法
           【1】私有的静态变量
            class user:
                __country = 'china'   # 私有的静态变量
                def func(self):
                    print(user.__country)  # 在类的内部可以调用
            # print(user.country)  # 报错 在类的外部不能调用
            # print(user.__country)# 报错 在类的外部不能调用
            user().func()#china
            
            【2】私有的实例变量
              class user:
                    def __init__(self,name,passwd):
                        self.usr = name
                        self.__pwd = passwd  # 私有的实例变量/私有的对象属性
                        
                    def get_pwd(self):       
                        return self.__pwd
             
                alex = user('alex','sbsbsb')
                print(alex.get_pwd())#sbsbsb
                
                        
            【3】私有的绑定方法
            import  hashlib
            class user:
                def __init__(self,name,passwd):
                    self.usr = name
                    self.__pwd = passwd  # 私有的实例变量
                def __get_md5(self):     # 私有的绑定方法
                    md5 = hashlib.md5(self.usr.encode('utf-8'))
                    md5.update(self.__pwd.encode('utf-8'))
                    return md5.hexdigest()
                def getpwd(self):
                    return self.__get_md5()
            alex = user('alex','sbsbsb')
            print(alex.getpwd())#d6170374823ac53f99e7647bab677b92
            
    4.私有的特点:
            能不能在类的内部使用?-能
            能不能在类的外部使用?-在外部不能直接调用
            能不能在类的子类中使用?-不能
            #面试题1:
            class foo(object):
                def __init__(self):
                    self.__func()
                def __func(self):  #_foo__func
                    print('in foo')
            class son(foo):
                def __func(self):  #_son__func
                    print('in son')
            son()#in foo
            
            #2:
            class foo(object):
                def __func(self):
                    print('in foo')
            class son(foo):
                def __init__(self):
                    self.__func()
            son()#报错:attributeerror: 'son' object has no attribute '_son__func'
            
            #3:
            class foo(object):
                def __init__(self):
                    self.func()
                def func(self):
                    print('in foo')
            class son(foo):
                def func(self):
                    print('in son')
            son()#in son
            
            
            
    5.原理:
            如何变形?【记】在类的内部使用的时候,自动的把当前这句话所在的类的名字拼在私有变量前完成变形。
            在哪里定义的时候变形? ---> 所有加双下划线的定义只有在类的内部定义的时候才会变成私有的, 在类的外部根本不能定义私有的概念。
            
            # 加了双下划线的名字为啥不能从类的外部调用了?
            class user:
                __country = 'china'   # 私有的静态变量
                __role = '法师'   # 私有的静态变量
                def func(self):
                    print(self.__country)  # 在类的内部使用的时候,自动的把当前这句话所在的类的名字拼在私有变量前完成变形
                    
            print(user._user__country)#china
            print(user._user__role)#法师
            
            # __country -->'_user__country': 'china'
            # __role    -->'_user__role': '法师'
            
            # user.__aaa = 'bbb'  # 在类的外部根本不能定义私有的概念,不会变成私有的。
            
            print(user.__dict__)
            #{'__module__': '__main__', '_user__country': 'china', '_user__role': '法师', 'func': <function user.func at 0x0000021fbe609c80>, '__dict__': <attribute '__dict__' of 'user' objects>, '__weakref__': <attribute '__weakref__' of 'user' objects>, '__doc__': none}
            
   6.类中变量的级别,哪些是python支持的,哪些是python不支持的
            # 在其他语言中的数据的级别都有哪些?在python中有哪些?
             【1】public  公有的 类内类外都能用,父类子类都能用        python支持
        
             【2】protect 保护的 类内能用,父类子类都能用,类外不能用    python不支持
            
             【3】private 私有的 本类的类内部能用,其他地方都不能用     python支持

super,封装,类中的三个装饰器,反射

super,封装,类中的三个装饰器,反射

3.类中的三个装饰器(内置函数)

​ 1.property

    1. @property :
        【1】把一个方法伪装成一个属性,在调用这个方法的时候不需要加()就可以直接得到返回值  
        【2】property装饰的这个方法 是 不能有参数的。
        
        变量的属性和方法?
             属性 :圆形的半径\圆形的面积\name\age
             方法 :登录  注册
        #1:
            from math import pi
            class circle:
                def __init__(self,r):
                    self.r = r

                @property   # 把一个方法伪装成一个属性,在调用这个方法的时候不需要加()就可以直接得到返回值
                def area(self):
                    return pi * self.r**2

            c1 = circle(5)
            print(c1.r)#5
            print(c1.area)#78.53981633974483
        
        #2:
            import time
            class person:
                def __init__(self,name,birth):
                    self.name = name
                    self.birth = birth
                @property
                def age(self):   # 装饰的这个方法 不能有参数
                    return time.localtime().tm_year - self.birth  #通过计算才能拿到某个结果,这个结果又直接是一个属性值,把一个方法伪装成属性

            太白 = person('太白',1998)
            print(太白.age)#21
          
        #3: 
         property的第二个应用场景 : 和私有的属性合作的,把相关的方法伪装成私有属性
            
            class user:
                def __init__(self,usr,pwd):
                    self.usr = usr
                    self.__pwd = pwd  #定义成私有
                @property
                def pwd(self):
                    return self.__pwd  #可以看,但不能改

            alex = user('alex','sbsbsb')
            print(alex.pwd)#sbsbsb
        
        #4:
        #商品打折的应用场景
            class goods:
                discount = 0.8
                def __init__(self,name,origin_price):
                    self.name = name
                    self.__price = origin_price  #私有化
                
                @property
                def price(self):
                    return self.__price * self.discount

            apple = goods('apple',5)
            print(apple.price)#4.0  
        
        #5:property进阶1(了解)
            class goods:
                discount = 0.8
                def __init__(self,name,origin_price):
                    self.name = name
                    self.__price = origin_price
                @property
                def price(self):
                    return self.__price * self.discount

                @price.setter  #@ 方法名.setter  三个地方的名字一致,比如都是price
                def price(self,new_value):  #定义一个和上面的property装饰的方法同名的方法,可以比上面多接收一个参数
                    if isinstance(new_value,int):  #只有new_value是int类型才允许修改
                        self.__price = new_value  #修改

            apple = goods('apple',5)
            print(apple.price) # 4.0    # 对象.名字 -->调用的是被 @property 装饰的price

            apple.price = 10            # 对象.名字 = xx -->调用的是被 setter 装饰的price  重新赋值
            print(apple.price) # 8.0   如果没有apple.price = 10 ,此处结果还是4.0
        
        #6:property进阶2(了解)
            class goods:
                discount = 0.8
                def __init__(self,name,origin_price):
                    self.name = name
                    self.__price = origin_price
                @property
                def price(self):
                    return self.__price * self.discount

                @price.setter
                def price(self,new_value):
                    if isinstance(new_value,int):
                        self.__price = new_value

                @price.deleter
                def price(self):     #5 个price必须是同样的名字
                    del self.__price #删除私有属性
                    
            apple = goods('apple',5)
            print(apple.price)#4.0   #调用property装饰的方法
            apple.price = 'ashkaksk'  #不能修改
            print(apple.price)#4.0   #调用setter装饰的方法
            del apple.price   # 调用deleteer装饰的方法。del apple.price 并不能真的删除什么,只是调用对应的被@price.deleter装饰的方法del self.__price而已
            print(apple.price)#attributeerror: 'goods' object has no attribute '_goods__price'
    
    

​ 2.classmethod

        【1】引入:
            #修改折扣,所有商品都修改。
            class goods:
                __discount = 0.8
                def __init__(self):
                    self.__price = 5
                    self.price = self.__price * self.__discount
                def change_discounnt(self,new_discount):  #传入了self 和 new_discount两个参数,但是self没有用上。一般在函数中不要传入一个用不到的参数。
                    goods.__discount = new_discount       #有一个change_discounnt方法默认传self参数,但在本函数中用不到该参数

            apple = goods()
            print(apple.price) # 4
            apple.change_discounnt(0.5) #不太符合逻辑,所有商品折扣的修改不应该依赖于某一个对象。此处为了调用到修改折扣的方法还必须先实例化一个对象
            apple2 = goods()
            print(apple2.price)#2.5

        【2】classmethod
        
              @classmethod   
                 把一个对象绑定的方法 修改成一个 类方法,被装饰的方法会成为一个类方法。
                 第一,在方法中仍然可以引用 类中的 静态变量
                 第二,可以不用实例化对象,就直接用类名在外部调用这个方法
            
             什么时候用@classmethod?
                 1.定义了一个方法,默认传self,但这个self没被使用
                 2.并且你在这个方法里用到了当前的类名, 或者你准备使用这个类的内存空间中的名字的时候

            class goods:  #cls指向当前所在类的名字,在类内部统一使用cls的话,修改类名时只需修改class后的类名,内部不用修改,非常方便
                __discount = 0.8
                def __init__(self):
                    self.__price = 5
                    self.price = self.__price * self.__discount
                @classmethod ## 把一个对象绑定的方法 修改成一个 类方法 ,self 改为 cls,cls指向当前所在类的名字,而不是指向对象的名字了。
                def change_discounnt(cls,new_discount):
                    # print(cls,goods)#<class '__main__.goods'> <class '__main__.goods'>
                    cls.__discount = new_discount

            #可以不用实例化对象,(在实例化之前)就能直接用类名在外部调用这个方法
            goods.change_discounnt(0.6)  #  类方法可以通过类名调用。不用对象就能调用这个方法了。相当于把goods也当做一个参数,传g给了cls。change_discounnt(cls,new_discount)
            apple = goods()
            print(apple.price)#3

            apple.change_discounnt(0.5)  # 类方法可以通过对象名调用
            apple2 = goods()
            print(apple2.price)#2.5
            
            #例:在自己类里做了自己类的实例化
            import time
            class date:
                def __init__(self,year,month,day):
                    self.year = year
                    self.month = month
                    self.day = day
                @classmethod
                def today(cls):  #类方法-->传cls
                    struct_t = time.localtime()
                    date = cls(struct_t.tm_year,struct_t.tm_mon,struct_t.tm_mday) #在自己类里做了自己类的实例化,做了开辟对象空间,调用__init__等操作,把self作为返回值传给date
                    return date  #将对象返回回去

            date对象 = date.today()
            print(date对象.year)#2019
            print(date对象.month)#6
            print(date对象.day)#5

​ 3.staticmethod

            # @staticmethod  被装饰的方法会成为一个静态方法
           本身是一个普通的函数,被挪到类的内部执行,那么直接给这个函数添加@staticmethod装饰器就可以了, 在函数的内部既不会用到self变量,也不会用到cls类。

            class user:
                pass
                @staticmethod
                def login(a,b):      # 本身是一个普通的函数,被挪到类的内部执行,那么直接给这个函数添加@staticmethod装饰器就可以了
                    print('登录的逻辑',a,b)
                    # 在函数的内部既不会用到self变量,也不会用到cls类

            obj = user()
            user.login(1,2)#登录的逻辑 1 2
            obj.login(3,4) #登录的逻辑 3 4
            
            
        总结:
        
        class a:
            country = '中国'  #静态变量
            def func(self):   #绑定方法
                print(self.__dict__)
            @classmethod
            def clas_func(cls):  #类方法
                print(cls)
            @staticmethod
            def stat_func():  #静态方法
                print('普通函数')
            @property
            def name(self):  #是个伪装成属性的方法
                return 'wahaha'
       
      能定义到类中的内容:
        【1】 静态变量 是个所有的对象共享的变量   由对象\类调用 但是使用对象不能对其重新赋值
        【2】 绑定方法 是个自带self参数的函数    由对象调用
        【3】 类方法   是个自带cls参数的函数     由对象\类调用
        【4】 静态方法 是个啥都不带的普通函数     由对象\类调用
        【5】 property属性 是个伪装成属性的方法  由对象调用 但不加括号
4.反射

反射:用字符串数据类型的名字 来操作这个名字对应的函数\实例变量\绑定方法\各种方法

1.引入:
        #用户输入一个名字,你来打印这个变量的值
        name = 'alex'
        age = 123
        n = input('>>>')
        if n == 'name':print(name)
        elif n == 'age':print(age)
2.有些时候 你明明知道一个变量的字符串数据类型的名字,你想直接调用它,但是调不到-->使用反射
     【1】反射对象的 实例变量(属性)
     【2】反射类的 静态变量/绑定方法/其他方法
     【3】模块中的 所有变量
          a.被导入的模块
          b.当前执行的py文件 - 脚本
            
    hasattr
    getattr: 字符串数据类型的变量名,采用getattr(对象,'变量名')获取变量的值。python中一切皆对象,此处对象可以是对象名,类名,模块名,本文件名
    callable:判断一个变量是不是可调用的,判断这个变量后面能不能加括号
    
    #1:  
       对象名.属性名 ==> getattr(对象名,'属性名')
        
        class person:
            def __init__(self,name,age):
                self.name = name
                self.age = age
            def qqxing(self):
                print('qqxing')

        alex = person('alex',83)
        wusir = person('wusir',74)
        ret = getattr(alex,'name')#反射对象的实例变量  
        print(ret)#alex
        ret = getattr(wusir,'name')
        print(ret)#wusir
        ret = getattr(wusir,'qqxing')#反射类的绑定方法
        ret()#qqxing  函数地址 + () 函数的调用
    
    #2:
        #a.py模块 
            class wechat:pass
            class alipay:pass

            def sww():
                print('爽歪歪')
            lst = [1,2,3,4,5]
            dic = {'k':'v'}
            we = wechat()
        
        #当前脚本:反射被导入模块中的 所有变量
        
            a.alipay ==> getattr(a,'alipay')
            ##1:
            import a
            print(a.wechat)#<class 'a.wechat'>
            print(a.alipay)#<class 'a.alipay'>

            # 对象名.属性名 ==> getattr(对象名,'属性名')
            # a.alipay ==> getattr(a,'alipay')

            print(getattr(a, 'alipay'))#<class 'a.alipay'>
            print(getattr(a, 'wechat'))#<class 'a.wechat'>

            ##2:
            import a
            import sys
            print(sys.modules)
            print(sys.modules['a'].alipay)#<class 'a.alipay'>
            print(a.alipay)#<class 'a.alipay'>
            print(getattr(a,'alipay'))#<class 'a.alipay'>
            print(getattr(sys.modules['a'],'alipay'))#<class 'a.alipay'>
            
    #3:反射当前脚本中 所有变量
            import sys
            wahaha = 'hahaha'
            print(getattr(sys.modules['__main__'],'wahaha'))#hahaha

     #4总结:【记】  
            class a:
                    role = '治疗'
                    def __init__(self):
                        self.name = 'alex'
                        self.age = 84
                    def func(self):
                        print('wahaha')
                        return 666

            a = a()
            print(getattr(a,'name'))   #alex                         # 反射对象的实例变量
            print(getattr(a,'func')()) # 函数地址 + () wahaha   666  # 反射对象的绑定方法
            print(getattr(a,'role'))   # 治疗

            import a   # 引用模块中的任意的变量
            print(getattr(a,'sww'),a.sww)#<function sww at 0x0000011b59b89b70> <function sww at 0x0000011b59b89b70>
            getattr(a,'sww')()          #爽歪歪
            print(getattr(a,'lst'),a.lst)#[1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
            print(getattr(a,'dic'),a.dic)#{'k': 'v'} {'k': 'v'}
            print(getattr(a,'we'),a.we) #<a.wechat object at 0x0000011b59b8e748> <a.wechat object at 0x0000011b59b8e748>

            import sys # 反射本模块中的名字
            cat = '小a'
            dog = '小b'
            def pig():
                print('小p')
            print(getattr(sys.modules['__main__'],'cat'))#小a
            print(getattr(sys.modules['__main__'],'dog'))#小b
            getattr(sys.modules['__main__'],'pig')()     #小p

   #5.反射应用的例子:
            class payment:pass
            class alipay(payment):
                def __init__(self,name):
                    self.name = name
                def pay(self,money):
                    dic = {'uname':self.name,'price':money}
                    print('%s通过支付宝支付%s钱成功'%(self.name,money))

            class wechat(payment):
                def __init__(self,name):
                    self.name = name
                def pay(self,money):
                    dic = {'username':self.name,'money':money}
                    print('%s通过微信支付%s钱成功'%(self.name,money))

            class apple(payment):
                def __init__(self,name):
                    self.name = name
                def pay(self,money):
                    dic = {'name': self.name, 'number': money}
                    print('%s通过苹果支付%s钱成功' % (self.name, money))

            class qqpay:
                def __init__(self,name):
                    self.name = name
                def pay(self,money):
                    print('%s通过qq支付%s钱成功' % (self.name, money))

            import sys
            def pay(name,price,kind):   #归一化合计
                class_name = getattr(sys.modules['__main__'],kind)  #关键1
                obj = class_name(name)                              #关键2
                obj.pay(price)                                      #关键3  这三行替代了下面被注释的代码
                # if kind == 'wechat':
                #     obj = wechat(name)
                # elif kind == 'alipay':
                #     obj = alipay(name)
                # elif kind == 'apple':
                #     obj = apple(name)
                # obj.pay(price)

            pay('alex',400,'wechat')
            pay('alex',400,'alipay')
            pay('alex',400,'apple')
            pay('alex',400,'qqpay')

            #结果:
            # alex通过微信支付400钱成功
            # alex通过支付宝支付400钱成功
            # alex通过苹果支付400钱成功
            # alex通过qq支付400钱成功

 #6:
        class a:
        role = '治疗'
        def __init__(self):
            self.name = 'alex'
            self.age = 84
        def func(self):
            print('wahaha')
            return 666

        a = a()
        print(hasattr(a,'sex'))#false
        print(hasattr(a,'age'))#true
        print(hasattr(a,'func'))#true
        if hasattr(a,'func'):  # 
            if callable(getattr(a,'func')):  #可调用的
                getattr(a,'func')()  #wahaha
   #7.反射的例子:文件操作
        # 文件操作
        class file:
            lst = [('读文件','read'), ('写文件','write'),
                   ('删除文件','remove'),( '文件重命名','rename'),
                   ('复制','copy'),('移动文件','move')]
            def __init__(self,filepath):
                self.filepath = filepath
            def write(self):
                print('in write func')
            def read(self):
                print('in read func')
            def remove(self):
                print('in remove func')
            def rename(self):
                print('in rename func')
            def copy(self):
                print('in copy func')
            def move(self):
                print('in 移动文件 func')

        f = file('ashkgkfj')
        while true:
            for index,opt in enumerate(file.lst,1):
                print(index,opt[0])
            num = int(input('请输入您要做的操作序号>>'))
            if hasattr(f,file.lst[num-1][1]):
                getattr(f,file.lst[num-1][1])()
总结:
1. super:
     super遵循的是mro算法
     只在新式类中能使用
     py2新式类中需要自己添加参数(子类名,子类对象)
        
2. 封装:
     广义上的封装
     狭义上的封装 __名字
         私有化:
             方法名私有化
             实例变量私有化
             静态变量私有化
                
         私有化的特点:
             只能在类的内部使用,不能在外部使用
                
         私有的各种静态变量和方法能不能继承:
             不能被子类继承
3. 内置函数
     [1]判断一个变量是不是可调用的,判断这个变量后面能不能加括号
        # callable(名字)
        
     [2]装饰器
        【1】 @property   把一个方法伪装成属性,使它调用的时候不用加括号  (重点)
            # 给伪装成属性的方法赋值 @函数名.setter装饰器
        
        【2】 @classmethod  *****(重点)
            # 什么时候用?
            # 怎么定义?
                # 装饰器怎么加?
                # 参数怎么改?
            # 怎么用?
                # 用谁来调用?
        【3】 @staticmethod *
            # 什么时候用?
                # 帮助我们把一个普通的函数挪到类中来直接使用,制造静态方法用的
            # 怎么定义?
            # 怎么用?用谁来调用?
        
     [3]反射相关
         hasattr
         getattr
         字符串数据类型的变量名,采用getattr(对象,'变量名')获取变量的值