Python高級(jí)語(yǔ)法4:類對(duì)象和實(shí)例對(duì)象訪問屬性的區(qū)別和property屬性

一、再論靜態(tài)方法和類方法以及實(shí)例方法

  • 1.1、類屬性辜荠、實(shí)例屬性
    它們?cè)诙x和使用中有所區(qū)別辐宾,而最本質(zhì)的區(qū)別內(nèi)存中保存的位置不同

    • 實(shí)例屬性屬于對(duì)象

    • 類屬性屬于類

      class Province(object):
            # 類屬性
            country = '中國(guó)'
      
            def __init__(self, name):
                  # 實(shí)例屬性
                  self.name = name
      
      
      # 創(chuàng)建一個(gè)實(shí)例對(duì)象
      obj = Province('山東省')
      # 直接訪問實(shí)例屬性
      print(obj.name)
      # 直接訪問類屬性
      Province.country
      

      由上述代碼可以看出【實(shí)例屬性需要通過對(duì)象來(lái)訪問】【類屬性通過類訪問】誉察,在使用上可以看出 實(shí)例屬性和類屬性的歸屬是不同的

      • 類屬性在內(nèi)存中只保存一份
      • 實(shí)例屬性在每個(gè)對(duì)象中都要保存一份
    • 應(yīng)用場(chǎng)景:通過類創(chuàng)建實(shí)例對(duì)象時(shí)惹谐,如果每個(gè)對(duì)象需要具有相同名字的屬性氨肌,那么就使用類屬性鸿秆,用一份既可

  • 1.2贩虾、實(shí)例方法策精、靜態(tài)方法和類方法 (類里面的三種方法,區(qū)別在于調(diào)用方式不同)

    • 實(shí)例方法:由對(duì)象調(diào)用易茬;至少一個(gè)self參數(shù)酬蹋;執(zhí)行實(shí)例方法時(shí),自動(dòng)將調(diào)用該方法的對(duì)象賦值給self食铐;

    • 類方法:由類調(diào)用匕垫; 至少一個(gè)cls參數(shù);執(zhí)行類方法時(shí)虐呻,自動(dòng)將調(diào)用該方法的類賦值給cls象泵;

    • 靜態(tài)方法:由類調(diào)用;無(wú)默認(rèn)參數(shù)斟叼;

      class Foo(object):
           def __init__(self, name):
                 self.name = name
      
      def ord_func(self):
           """ 定義實(shí)例方法偶惠,至少有一個(gè)self參數(shù) """
           # print(self.name)
           print('實(shí)例方法')
      
      @classmethod
      def class_func(cls):
           """ 定義類方法,至少有一個(gè)cls參數(shù) """
           print('類方法')
      
      @staticmethod
      def static_func():
           """ 定義靜態(tài)方法 朗涩,無(wú)默認(rèn)參數(shù)"""
           print('靜態(tài)方法')
      
      
      f = Foo("中國(guó)")
      # 調(diào)用實(shí)例方法
      f.ord_func()
      
      # 調(diào)用類方法
      Foo.class_func()
      
      # 調(diào)用靜態(tài)方法
      Foo.static_func()
      
      • 相同點(diǎn):對(duì)于所有的方法而言忽孽,均屬于類,所以 在內(nèi)存中也只保存一份
      • 不同點(diǎn):方法調(diào)用者不同谢床、調(diào)用方法時(shí)自動(dòng)傳入的參數(shù)不同兄一。

二、property 屬性

  • 2.1识腿、什么是property屬性出革,在方法名的加上property就是 property屬性,在調(diào)用上 dog.run 優(yōu)于 dog.eat()

    class Dog(object):
    
          def eat(self):
                print("吃")
    
          # 定義property屬性
          @property
          def run(self):
                print("跑")
    
    dog = Dog()
    dog.eat()  # 調(diào)用實(shí)例方法
    dog.run    # 調(diào)用property屬性
    
    • property屬性的定義和調(diào)用要注意一下幾點(diǎn):
      • 定義時(shí)渡讼,在實(shí)例方法的基礎(chǔ)上添加 @property 裝飾器蹋盆;并且僅有一個(gè)self參數(shù)

      • 調(diào)用時(shí)费薄,無(wú)需括號(hào)

        方法:dog.eat() 
        property屬性:dog.run
        
  • 2.2、property屬性有兩種方式

    • 裝飾器 即:在方法上應(yīng)用裝飾器

    • 類屬性 即:在類中定義值為property對(duì)象的類屬性

    • 2.2.1栖雾、裝飾器方式
      在類的實(shí)例方法上應(yīng)用@property裝飾器楞抡,Python中的類有經(jīng)典類和新式類,新式類的屬性比經(jīng)典類的屬性豐富析藕。( 如果類繼object召廷,那么該類是新式類

      • 經(jīng)典類,具有一種@property裝飾器

        class Goods:
           @property
           def price(self):
                return "laowang"
        # ############### 調(diào)用 ###############
        obj = Goods()
        result = obj.price  # 自動(dòng)執(zhí)行 @property 修飾的 price 方法账胧,并獲取方法的返回值
        print(result)
        
      • 新式類竞慢,具有三種@property裝飾器

        # ############### 定義 ###############
        class Goods:
              """python3中默認(rèn)繼承object類
              以python2、3執(zhí)行此程序的結(jié)果不同治泥,因?yàn)橹挥性趐ython3中才有@xxx.setter  @xxx.deleter
              """
              @property
              def price(self):
                   print('@property')
        
              @price.setter
              def price(self, value):
                   print('@price.setter')
        
              @price.deleter
              def price(self):
                   print('@price.deleter')
        
        # ############### 調(diào)用 ###############
        obj = Goods()
        obj.price          # 自動(dòng)執(zhí)行 @property 修飾的 price 方法筹煮,并獲取方法的返回值
        obj.price = 123    # 自動(dòng)執(zhí)行 @price.setter 修飾的 price 方法,并將  123 賦值給方法的參數(shù)
        del obj.price      # 自動(dòng)執(zhí)行 @price.deleter 修飾的 price 方法
        

        注意

        • 經(jīng)典類中的屬性只有一種訪問方式居夹,其對(duì)應(yīng)被 @property 修飾的方法
        • 新式類中的屬性有三種訪問方式败潦,并分別對(duì)應(yīng)了三個(gè)被@property、@方法名.setter准脂、@方法名.deleter修飾的方法

        由于新式類中具有三種訪問方式劫扒,我們可以根據(jù)它們幾個(gè)屬性的訪問特點(diǎn),分別將三個(gè)方法定義為對(duì)同一個(gè)屬性:獲取狸膏、修改沟饥、刪除

        class Goods(object):
        
             def __init__(self):
                 # 原價(jià)
                 self.original_price = 100
                 # 折扣
                 self.discount = 0.8
        
             @property
             def price(self):
                 # 實(shí)際價(jià)格 = 原價(jià) * 折扣
                 new_price = self.original_price * self.discount
                 return new_price
        
             @price.setter
             def price(self, value):
                 self.original_price = value
        
             @price.deleter
             def price(self):
                 del self.original_price
        
        obj = Goods()
        obj.price         # 獲取商品價(jià)格
        obj.price = 200   # 修改商品原價(jià)
        del obj.price     # 刪除商品原價(jià)
        
    • 2.2.2、類屬性 方式湾戳,創(chuàng)建值為property對(duì)象的類屬性,我比較喜歡這個(gè)方式

      • 當(dāng)使用 類屬性 的方式創(chuàng)建 property屬性 時(shí)贤旷,經(jīng)典類新式類 無(wú)區(qū)別

        class Person:
           def get_name(self):
              return 'laowang'
        
           BAR = property(get_name)
        
        obj = Person()
        reuslt = obj.BAR  # 自動(dòng)調(diào)用get_bar方法,并獲取方法的返回值
        print(reuslt)
        
      • property 方法中有個(gè) 四個(gè)參數(shù)

        • 第 1 個(gè)參數(shù)是方法名砾脑,調(diào)用 對(duì)象.屬性 時(shí)自動(dòng)觸發(fā)執(zhí)行方法
        • 第 2 個(gè)參數(shù)是方法名幼驶,調(diào)用 對(duì)象.屬性 = XXX 時(shí)自動(dòng)觸發(fā)執(zhí)行方法
        • 第 3 個(gè)參數(shù)是方法名,調(diào)用 del 對(duì)象.屬性 時(shí)自動(dòng)觸發(fā)執(zhí)行方法
        • 第 4 個(gè)參數(shù)是字符串拦止,調(diào)用 對(duì)象.屬性.__doc__ 县遣,此參數(shù)是該屬性的描述信息
      class Person(object):
      
           def __init__(self,name):
                self.name = name
      
           def get_name(self): 
                return self.name
      
           def set_name(self,new_name):
      
                self.name = new_name
                print("設(shè)置名字為:%s"%self.name)
      
           def del_name(self):
                del  self.name
      
           BAR = property(get_name,set_name,del_name,"描述信息...")
      
      
      person = Person("小王")
      person.BAR      # 自動(dòng)調(diào)用第一個(gè)參數(shù)中定義的方法:get_name
      person.BAR = "小李" # 自動(dòng)調(diào)用第二個(gè)參數(shù)中定義的方法:set_name方法糜颠,并將 "小李" 當(dāng)作參數(shù)傳入
      
      person.del_name  # 自動(dòng)調(diào)用第三個(gè)參數(shù)中定義的方法:del_name方法
      
      desc = Person.BAR.__doc__   # 自動(dòng)獲取第四個(gè)參數(shù)中設(shè)置的值:描述信息...
      
      print("描述是:%s"%desc)
      

      由于類屬性方式創(chuàng)建 property屬性 具有3種訪問方式汹族,我們可以根據(jù)它們幾個(gè)屬性的訪問特點(diǎn),分別將 三個(gè)方法定義為對(duì)同一個(gè)屬性:獲取其兴、修改顶瞒、刪除,如下商品的價(jià)格

      class Goods(object):
      
          def __init__(self):
              # 原價(jià)
              self.original_price = 100
              # 折扣
              self.discount = 0.8
      
          def get_price(self):
              # 實(shí)際價(jià)格 = 原價(jià) * 折扣
              new_price = self.original_price * self.discount
              return new_price
      
          def set_price(self, value):
              self.original_price = value
      
          def del_price(self):
              del self.original_price
      
          PRICE = property(get_price, set_price, del_price, '價(jià)格屬性描述...')
      
      obj = Goods()
      obj.PRICE         # 獲取商品價(jià)格
      obj.PRICE = 200   # 修改商品原價(jià)
      del obj.PRICE     # 刪除商品原價(jià)
      
  • 2.3、Django框架中應(yīng)用了property屬性(了解)
    WEB框架 Django 的視圖中 request.POST 就是使用的類屬性的方式創(chuàng)建的屬性

    class WSGIRequest(http.HttpRequest):
          def __init__(self, environ):
               script_name = get_script_name(environ)
               path_info = get_path_info(environ)
               if not path_info:
                  # Sometimes PATH_INFO exists, but is empty (e.g. accessing
                  # the SCRIPT_NAME URL without a trailing slash). We really need to
                  # operate as if they'd requested '/'. Not amazingly nice to force
                  # the path like this, but should be harmless.
                  path_info = '/'
               self.environ = environ
               self.path_info = path_info
               self.path = '%s/%s' % (script_name.rstrip('/'), path_info.lstrip('/'))
               self.META = environ
               self.META['PATH_INFO'] = path_info
               self.META['SCRIPT_NAME'] = script_name
               self.method = environ['REQUEST_METHOD'].upper()
               _, content_params = cgi.parse_header(environ.get('CONTENT_TYPE', ''))
               if 'charset' in content_params:
                       try:
                           codecs.lookup(content_params['charset'])
                       except LookupError:
                           pass
                       else:
                           self.encoding = content_params['charset']
               self._post_parse_error = False
               try:
                    content_length = int(environ.get('CONTENT_LENGTH'))
               except (ValueError, TypeError):
                    content_length = 0
               self._stream = LimitedStream(self.environ['wsgi.input'], content_length)
               self._read_started = False
               self.resolver_match = None
    
           def _get_scheme(self):
               return self.environ.get('wsgi.url_scheme')
    
           def _get_request(self):
               warnings.warn('`request.REQUEST` is deprecated, use `request.GET` or '
                   '`request.POST` instead.', RemovedInDjango19Warning, 2)
               if not hasattr(self, '_request'):
                     self._request = datastructures.MergeDict(self.POST, self.GET)
               return self._request
    
            @cached_property
            def GET(self):
                  # The WSGI spec says 'QUERY_STRING' may be absent.
                  raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '')
                  return http.QueryDict(raw_query_string, encoding=self._encoding)
    
            # ############### 看這里看這里  ###############
           def _get_post(self):
                 if not hasattr(self, '_post'):
                     self._load_post_and_files()
                 return self._post
    
           # ############### 看這里看這里  ###############
           def _set_post(self, post):
                 self._post = post
    
           @cached_property
           def COOKIES(self):
                 raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '')
                 return http.parse_cookie(raw_cookie)
    
           def _get_files(self):
                 if not hasattr(self, '_files'):
                     self._load_post_and_files()
                 return self._files
    
           # ############### 看這里看這里  ###############
           POST = property(_get_post, _set_post)
    
    FILES = property(_get_files)
    REQUEST = property(_get_request)
    

綜上所述

  • 定義property屬性共有兩種方式元旬,分別是【裝飾器】和【類屬性】榴徐,而【裝飾器】方式針對(duì)經(jīng)典類和新式類又有所不同守问。
  • 通過使用property屬性,能夠簡(jiǎn)化調(diào)用者在獲取數(shù)據(jù)的流程
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坑资,一起剝皮案震驚了整個(gè)濱河市耗帕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袱贮,老刑警劉巖仿便,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異攒巍,居然都是意外死亡嗽仪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門柒莉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)闻坚,“玉大人,你說我怎么就攤上這事兢孝×铮” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵西潘,是天一觀的道長(zhǎng)卷玉。 經(jīng)常有香客問我,道長(zhǎng)喷市,這世上最難降的妖魔是什么相种? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮品姓,結(jié)果婚禮上寝并,老公的妹妹穿的比我還像新娘。我一直安慰自己腹备,他們只是感情好衬潦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著植酥,像睡著了一般镀岛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上友驮,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天漂羊,我揣著相機(jī)與錄音,去河邊找鬼卸留。 笑死走越,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的耻瑟。 我是一名探鬼主播旨指,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼赏酥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了谆构?” 一聲冷哼從身側(cè)響起裸扶,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎搬素,沒想到半個(gè)月后姓言,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔗蹋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年何荚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猪杭。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡餐塘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出皂吮,到底是詐尸還是另有隱情戒傻,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布蜂筹,位于F島的核電站需纳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏艺挪。R本人自食惡果不足惜不翩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望麻裳。 院中可真熱鬧口蝠,春花似錦、人聲如沸津坑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)疆瑰。三九已至眉反,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間穆役,已是汗流浹背寸五。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留孵睬,地道東北人播歼。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓伶跷,卻偏偏與公主長(zhǎng)得像掰读,于是被迫代替她去往敵國(guó)和親秘狞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容