亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Python中的動(dòng)態(tài)屬性和特性

 更新時(shí)間:2018年04月07日 15:39:51   作者:Hanwencheng  
本篇文章主要介紹了詳解Python中的動(dòng)態(tài)屬性和特性,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

導(dǎo)語(yǔ):本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之元編程篇的重點(diǎn)知識(shí)及個(gè)人心得,打算入門Python的朋友們可以來(lái)一起學(xué)習(xí)并交流。

一、利用動(dòng)態(tài)屬性處理JSON數(shù)據(jù)源

屬性:在Python中,數(shù)據(jù)的屬性和處理數(shù)據(jù)的方法統(tǒng)稱屬性。

元編程:用元類進(jìn)行編程,元類→類→對(duì)象,元類比類更抽象,生成類的類。

1、使用動(dòng)態(tài)屬性訪問(wèn)JSON類數(shù)據(jù)

第一版:利用json.load(fp)審查數(shù)據(jù)

from urllib.request import urlopen
import warnings
import os
import json

URL = 'http://www.oreilly.com/pub/sc/osconfeed'
JSON = 'data/osconfeed.json'

def load():
  if not os.path.exists(JSON):
    msg = 'downloading {} to {}'.format(URL, JSON)
    warnings.warn(msg) #如果需要下載就發(fā)出提醒。
    with urlopen(URL) as remote, open(JSON, 'wb') as local: #在with語(yǔ)句中使用兩個(gè)上下文管理器分別用于讀取和保存遠(yuǎn)程文件。
      local.write(remote.read())
  with open(JSON) as fp:
    return json.load(fp)#json.load函數(shù)解析JSON文件,返回Python原生對(duì)象。

第二版:使用動(dòng)態(tài)屬性訪問(wèn)JSON類數(shù)據(jù)

第一版查閱深層數(shù)據(jù)的格式比較冗長(zhǎng),例如feed'Schedule'40,我們希望在讀取屬性上采用feed.Schedule.events[40].name這類方式來(lái)改進(jìn)。并且第二版的類能遞歸,自動(dòng)處理嵌套的映射和列表。

from collections import abc

class FronenJSON():
  def __init__(self,mapping):
    self.__data=dict(mapping)#創(chuàng)建副本,同時(shí)確保處理的是字典。
    
  def __getattr__(self, name):#僅當(dāng)沒(méi)有指定名稱的屬性才調(diào)用__getattr__方法。
    if hasattr(self,name):
      return getattr(self.__data,name)
    else:
      return FronenJSON.build(self.__data[name])
  
  @classmethod  
  def __build__(cls,obj):
    if isinstance(obj,abc.Mapping):#判斷obj是否是映射。
      return cls(obj)#創(chuàng)建FrozenJSON對(duì)象。
    elif isinstance(obj,abc.MutableSequence):
      return [cls.build(item) for item in obj]#遞歸調(diào)用.build()方法,構(gòu)建一個(gè)列表。
    else:#既不是字典也不是列表,則返回元素本身。
      return obj

分析: FronenJSON類的關(guān)鍵是__getattr__方法。僅當(dāng)無(wú)法使用常規(guī)的方式獲取屬性(即在實(shí)例、類或超類中找不到指定的屬性),解釋器才會(huì)調(diào)用特殊的__getattr__方法。

2、處理無(wú)效屬性名

在Python中,由于關(guān)鍵字被保留,名稱為關(guān)鍵字的屬性是無(wú)效的。因此需要對(duì)第二版中的__init__進(jìn)行改進(jìn):

  def __init__(self,mapping):
    self.__data={}
    for key,value in mapping.items():
      if keyword.iskeyword(key):
        key+='_'#與Python關(guān)鍵字重復(fù)的key在尾部加上下劃線。
      self.__data[key]=value

3、使用特殊方法__new__

第三版:使用__new__構(gòu)造方法把一個(gè)類轉(zhuǎn)換成一個(gè)靈活的對(duì)象工廠函數(shù)。

from collections import abc

class FronenJSON():
  def __new__(cls, arg): # __new__是類方法,第一個(gè)參數(shù)是類本身cls。
    if isinstance(arg, abc.Mapping):
      return super().__new__(cls) #委托給超類object基類的__new__方法處理。
    elif isinstance(arg, abc.MutableSequence): # 余下方法與原先的build方法一致。
      return [cls(item) for item in arg]
    else:
      return arg
 
   def __init__(self,mapping):
    self.__data={}
    for key,value in mapping.items():
      if keyword.iskeyword(key):
        key+='_'
      self.__data[key]=value 

  def __getattr__(self, name):
    if hasattr(self,name):
      return getattr(self.__data,name)
    else:
      return FronenJSON(self.__data[name]) 

二、特性

1、類屬性、實(shí)例屬性、私有屬性與特性

類屬性:類屬性在__init__()外初始化,屬于類所有,所有實(shí)例共享一個(gè)屬性。
調(diào)用方法:類屬性在內(nèi)部用classname.類屬性名調(diào)用,外部既可以用classname.類屬性名又可以用instancename.類屬性名來(lái)調(diào)用。

實(shí)例屬性:實(shí)例屬性屬于各個(gè)實(shí)例所有,互不干擾。

私有屬性:

  1. 單下劃線_開(kāi)頭:只是告訴別人這是私有屬性,外部依然可以訪問(wèn)更改。
  2. 雙下劃線__開(kāi)頭:外部不可通過(guò)instancename.propertyname來(lái)訪問(wèn)或者更改,實(shí)際將其轉(zhuǎn)化為了_classname__propertyname。

特性:是用于管理實(shí)例屬性的類屬性。
特性用途:經(jīng)常用于把公開(kāi)的屬性變成使用讀值方法和設(shè)值方法管理的屬性,且在不影響客戶端代碼的前提下實(shí)施業(yè)務(wù)規(guī)則。

注意:

  1. 不要對(duì)實(shí)例屬性和類屬性使用相同的名字。否則實(shí)例屬性會(huì)遮蓋類屬性,發(fā)生難以發(fā)現(xiàn)的錯(cuò)誤。
  2. 實(shí)例屬性不會(huì)遮蓋類特性,但類特性會(huì)遮蓋實(shí)例屬性。

這是因?yàn)閛bj.attr不會(huì)從實(shí)例obj開(kāi)始尋找attr,而是從obj.__class__開(kāi)始;而且僅當(dāng)類中沒(méi)有名為attr的特性時(shí),Python才會(huì)在實(shí)例中尋找attr。

簡(jiǎn)言之,就遮蓋層級(jí)而言,類特性>實(shí)例屬性>類屬性。

2、使用特性驗(yàn)證屬性

使用特性可以驗(yàn)證實(shí)例屬性的有效性,同時(shí)能夠根據(jù)已知屬性和屬性之間的關(guān)系式調(diào)整其他屬性,避免硬編碼。
案例:假設(shè)某商店經(jīng)營(yíng)堅(jiān)果、雜糧等多種有機(jī)食物,每位顧客的訂單會(huì)包含店中的一系列商品,我們需要根據(jù)客戶的訂單計(jì)算出總價(jià)。

分析:我們不希望顧客訂單的商品重量為非正數(shù),需要借助@property裝飾器實(shí)現(xiàn)值的獲取與設(shè)置,從而驗(yàn)證實(shí)例屬性的有效性。代碼如下:

class LineItem():
  def __init__(self,description,weight,price):
    self.description=description
    self.weight=weight
    self.price=price

  def subtotal(self):
    return self.weight*self.price

  @property#讀值。
  def weight(self):
    return self.__weight#真正的值存儲(chǔ)在私有屬性中。

  @weight.setter
  def weight(self,value):
    if value >0:
      self.__weight=value#有效值存入私有屬性中。
    else:
      raise ValueError('Value must be > 0')#對(duì)于無(wú)效的值拋出ValueError。

Tips:當(dāng)我們需要設(shè)置只讀屬性時(shí),只使用@property,無(wú)需使用@func.setter。

原理解析:為了更好地理解@property裝飾器的原理,我們寫(xiě)一版效果相同但沒(méi)使用裝飾器的代碼。

class LineItem:
  def __init__(self, description, weight, price):
    self.description = description
    self.weight = weight
    self.price = price

  def subtotal(self):
    return self.weight * self.price

  def get_weight(self): #普通讀值方法。
    return self.__weight

  def set_weight(self, value): #普通設(shè)值方法。
    if value > 0:
      self.__weight = value
    else:
      raise ValueError('value must be > 0')
  weight = property(get_weight, set_weight) #構(gòu)建property對(duì)象,賦值給公開(kāi)的類特性。

property 構(gòu)造方法的完整簽名:

property(fget=None, fset=None, fdel=None, doc=None)

3、特性工廠函數(shù)

抽象定義特性的方式有兩種,一是使用特性工廠函數(shù),二是使用描述符類。
下面我們用特性工廠函數(shù)來(lái)完成上文中提到的訂單結(jié)算案例:

def quantity(storage_name): 

  def qty_getter(instance): # instance指的是要把屬性存儲(chǔ)其中的LineItem實(shí)例。
    return instance.__dict__[storage_name] # 引用閉包中的自由變量storage_name,值直接從instance.__dict__中獲取,以便跳過(guò)特性,防止無(wú)限遞歸。

  def qty_setter(instance, value): 
    if value > 0:
      instance.__dict__[storage_name] = value # 同理存儲(chǔ),跳過(guò)特性。
    else:
      raise ValueError('value must be > 0')

  return property(qty_getter, qty_setter) # 構(gòu)建自定義特性對(duì)象并返回。

class LineItem:
  weight = quantity('weight') # 將自定義特性weight定義為類屬性。
  price = quantity('price') # 同上。

  def __init__(self, description, weight, price):
    self.description = description
    self.weight = weight # 此處特性已經(jīng)激活,可驗(yàn)證值的有效性。
    self.price = price

  def subtotal(self):
    return self.weight * self.price # 此處利用特性獲取實(shí)例中存儲(chǔ)的值。

4、使用特性刪除屬性

class BlackKnight:
 def __init__(self):
   self.members = ['an arm', 'another arm',
           'a leg', 'another leg']
   self.phrases = ["'Tis but a scratch.",
           "It's just a flesh wound.",
           "I'm invincible!",
           "All right, we'll call it a draw."]

 @property
 def member(self):
   print('next member is:')
   return self.members[0]

 @member.deleter
 def member(self):
   text = 'BLACK KNIGHT (loses {})\n-- {}'
   print(text.format(self.members.pop(0), self.phrases.pop(0)))

刪除屬性只需在主程序中發(fā)出指令:del obj.attr

三、處理屬性的重要屬性和函數(shù)

1、特殊屬性

  • __class__:對(duì)象所屬類的引用(即obj.__class__和type(obj)的作用相同)。Python中的某些特殊方法比如 __getattr__,只在對(duì)象的類中尋找,而不在實(shí)例中尋找。
  • __dict__:一個(gè)映射,存儲(chǔ)對(duì)象或類的可寫(xiě)屬性。
  • __slots__:類可以定義這個(gè)屬性,限制實(shí)例有哪些屬性。

2、內(nèi)置函數(shù)

  • dir([object]):列出對(duì)象的大多數(shù)屬性。
  • getattr(object,name[,default]):從object對(duì)象中獲取name字符串對(duì)應(yīng)的屬性。獲取的屬性可能來(lái)自對(duì)象所屬的類或超類。
  • hasattr(object,name):若object對(duì)象中存在指定的屬性,或者能以某種方式(如繼承)通過(guò)object對(duì)象獲取指定的屬性,返回True。
  • setattr(object,name,value):把object對(duì)象指定屬性的值設(shè)為value,前提是object對(duì)象能接受那個(gè)值。這個(gè)函數(shù)可能會(huì)創(chuàng)建一個(gè)新屬性,或者覆蓋現(xiàn)有的屬性。
  • var([object]):返回object對(duì)象的__dict__屬性。

3、特殊方法

  • __delattr__(self,name):只要使用del語(yǔ)句刪除屬性,就會(huì)調(diào)用這個(gè)方法。
  • __dir__(self):把對(duì)象傳給dir函數(shù)時(shí)調(diào)用,列出屬性。
  • __getattr__(self,name):僅當(dāng)獲取指定的屬性失敗,搜索過(guò)obj,Class和超類之后調(diào)用。
  • __getattribute__(self,name):嘗試獲取指定的屬性時(shí)總會(huì)調(diào)用這個(gè)方法。不過(guò)尋找的屬性是特殊屬性或特殊方法時(shí)除外。為了防止無(wú)限遞歸,__getattribute__方法的實(shí)現(xiàn)要使用super().__getattribute__(obj,name)。
  • __setattr__(self,name,value):嘗試設(shè)置指定的屬性時(shí)總會(huì)調(diào)用這個(gè)方法。點(diǎn)號(hào)和setattr內(nèi)置函數(shù)會(huì)觸發(fā)這個(gè)方法。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • tensorflow 查看梯度方式

    tensorflow 查看梯度方式

    今天小編就為大家分享一篇tensorflow 查看梯度方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-02-02
  • python excel和yaml文件的讀取封裝

    python excel和yaml文件的讀取封裝

    這篇文章主要介紹了python excel和yaml文件的讀取封裝,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2021-01-01
  • 如何用 Python 制作一個(gè)迷宮游戲

    如何用 Python 制作一個(gè)迷宮游戲

    這篇文章主要介紹了如何用 Python 制作一個(gè)迷宮游戲,幫助大家更好的理解和學(xué)習(xí)python,感興趣的朋友可以了解下
    2021-02-02
  • python實(shí)現(xiàn)統(tǒng)計(jì)文本中單詞出現(xiàn)的頻率詳解

    python實(shí)現(xiàn)統(tǒng)計(jì)文本中單詞出現(xiàn)的頻率詳解

    這篇文章主要介紹了python統(tǒng)計(jì)文本中單詞出現(xiàn)頻率,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • python字符串拼接的7種方法及性能比較詳解

    python字符串拼接的7種方法及性能比較詳解

    這篇文章主要介紹了python字符串拼接的7種方法詳解,需要的朋友可以參考下
    2021-04-04
  • 詳解使用django-mama-cas快速搭建CAS服務(wù)的實(shí)現(xiàn)

    詳解使用django-mama-cas快速搭建CAS服務(wù)的實(shí)現(xiàn)

    這篇文章主要介紹了詳解使用django-mama-cas快速搭建CAS服務(wù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Python3 完全平方數(shù)案例

    Python3 完全平方數(shù)案例

    這篇文章主要介紹了Python3 完全平方數(shù)的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • Python使用pyecharts繪制世界地圖,省級(jí)地圖,城市地圖實(shí)例詳解

    Python使用pyecharts繪制世界地圖,省級(jí)地圖,城市地圖實(shí)例詳解

    這篇文章主要介紹了如何使用Python中的pyecharts庫(kù)繪制世界地圖、中國(guó)地圖、省級(jí)地圖、市級(jí)地圖,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起動(dòng)手試一試
    2022-02-02
  • python的函數(shù)形參和返回值你了解嗎

    python的函數(shù)形參和返回值你了解嗎

    這篇文章主要為大家詳細(xì)介紹了python的函數(shù)形參和返回值,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • Python中執(zhí)行調(diào)用JS的多種實(shí)現(xiàn)方法總結(jié)

    Python中執(zhí)行調(diào)用JS的多種實(shí)現(xiàn)方法總結(jié)

    這篇文章主要給大家介紹了關(guān)于Python中執(zhí)行調(diào)用JS的多種實(shí)現(xiàn)方法,在一些特殊的python應(yīng)用場(chǎng)景下需要逆向執(zhí)行javascript代碼塊或者.js文件,需要的朋友可以參考下
    2023-08-08

最新評(píng)論