程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

python知識:裝飾器@property有啥用途?

編輯:Python

一、提要

        python的@property是python的一種裝飾器,是用來修飾方法的。python @property 裝飾器使一個方法可以像屬性一樣被使用。除此之外,還有幾個使用場景,本文將敘述這些使用技巧。

二、關於屬性的約定

首先看下屬性的分類:

2.1 類綁定屬性

一般類內屬性是指定義成與類同一存儲單元的屬性,可以類訪問。而當類實例化成對象後,類變量將做為拷貝加入對象,對象所訪問的屬性是一份拷貝。這份拷貝修改後易變。

 驗證代碼

class Stranger(object):
name = 'class name' #類綁定屬性
def __init__(self, gender=None ):
self.gender = gender #對象綁定屬性
self.name = 'new name' #對象中屬性,與類屬性的同名拷貝
stan = Stranger('male')
print(1,stan.gender)
stan.gender = 'famel'
print(2,stan.gender)
print(3 stan.name)
print( 4, Stranger.name)

結果:

1 male
2 famel
3 new name
4 class name

2.2 對象綁定屬性

凡用self定義的屬性,都是對象綁定屬性,

  • 內部調用時都需要加上self.
  • 外部調用時用 instance_name.property_name進行訪問
class Stranger(object):
def __init__(self, gender=None ):
self.gender = gender
stan = Stranger('roma')
print(stan.gender)
stan.gender = 'Paras'
print(stan.gender)

結果: 

roma
Paras 

注意:事實上實例化後的對象,也可以定義屬性,外部也可以調用。 

2.3 私有屬性 

        python的私有屬性沒有編譯限定,知識以單下劃線_開頭,標記此屬性是私有的,但是外部也可以自由訪問(私有的程度不夠多)。另一種是雙下劃線__開頭的屬性,可以轉化成類屬性訪問

  • 單下劃線_開頭:只是告訴別人這是私有屬性,外部依然可以訪問更改
  • 雙下劃線__開頭:外部不可通過instancename.propertyname來訪問或者更改,實際將其轉化為了_classname__propertyname

三、應用@property裝飾器

        python的@property是python的一種裝飾器,是用來修飾方法的。python @property 裝飾器使一個方法可以像屬性一樣被使用,而不需要在調用的時候帶上() 接下來我們會了解什麼時候需要使用它,並且在什麼場景下需要用到它以及如何合理的使用它。

python類中@property裝飾器,相配合的方法有:

  • setter() 
  • get() 
  • set()

相配合。
 

3.1 將一個屬性轉成方法

        將一個屬性轉化為一個方法時,我們最好加上一個@property 裝飾器來解決這個問題。在方法定義上面加一個@property 裝飾器,可以在不改變原有調用方式的同時,來將一個屬性改為一個方法。

class Goods():
def __init__(self,unit_price,weight):
self.unit_price = unit_price
self.weight = weight
@property
def price(self):
return self.unit_price * self.weight
lemons = Goods(7,4)
print(lemons.price)

   28    

 上文中,price是方法,現在將方法轉化成屬性調用。注意這個技巧,要知道原類定義中無price這個屬性,這是一個臨時產生的結果。類同於excel表格的“計算項”。

3.2 私有化某些屬性

        對於某些屬性,不可直接訪問。這裡的“直接”就是“無條件”的意思;而條件的訪問,就需要裝飾器 @property,下例是雙裝飾器@property和@age.setter配合,對_age進行條件隔離的例子:

class Stranger(object):
def __init__(self, gender=None, age=None, job=None):
self.gender = gender
self._age = age # 這裡的成員屬性_age需要與成員方法age()區分開
self.jobb = job
# 讀取age
@property # 實現一個age相關的getter方法
def age(self):
return self._age
# 設置age
@age.setter # 實現一個age相關的setter方法
def age(self, value):
if isinstance(value, int):
self._age = value
else:
raise ValueError("'int' type need")
if __name__ == "__main__":
# 創建一個“妹子”
meizi = Stranger()
meizi.age = 18 # 使用時注意是.age,不是._age
print("年齡:{age}".format(age=meizi.age))

注意事項:

  • 屬性名與方法名一定要區分開,不然會進入死循環(self._age,def age())
  • 實例化的對象使用屬性時,不是調用屬性(meizi._age),而是用的方法名(meizi.age)
  • @property其實就是實現了getter功能; @xxx.setter實現的是setter功能;還有一個 @xxx.deleter實現刪除功能
  • 定義方法的時候 @property必須在 @xxx.setter之前,且二者修飾的方法名相同(age())
  • 如果只實現了 @property(而沒有實現@xxx.setter),那麼該屬性為 只讀屬性

3.3 關聯性修改

比如,我們輸入了first_name、last_name可以得出fullname,下面代碼可以實現全名的屬性獲取。而反過來,對全名進行修改後,如何將連帶的first_name、last_name同步進行修改?。下文中的 @fullname.setter就是解決此類問題的。

class Person():
def __init__(self, first_name, last_name):
self.first = first_name
self.last = last_name
@property
def fullname(self):
return self.first + ' ' + self.last
@fullname.setter
def fullname(self, name):
first_name, last_name = name.split()
self.first = first_name
self.last = last_name
def email(self):
return '{}.{}@email.com'.format(self.first, self.last)
person = Person('zhang', 'san')
print(person.fullname)
print(person.last)
print(person.first)
person.fullname = 'li si'
print(person.fullname)
print(person.last)
print(person.first)

3.4 刪除屬性的deleter方法

        和setter 方法類似,當我們需要刪除一個屬性時,我們會使用deleter 方法。

        你可以像定義setter 方法一樣來定義一個setter 方法,使用相同的方法名,並在方法上添加@{methodname}.deleter 裝飾器 。

class Person():
def __init__(self, first_name, last_name):
self.first = first_name
self.last = last_name
@property
def fullname(self):
return self.first + ' ' + self.last
@fullname.setter
def fullname(self, name):
first_name, last_name = name.split()
self.first = first_name
self.last = last_name
@fullname.deleter
def fullname(self):
self.first = None
self.last = None
def email(self):
return '{}.{}@email.com'.format(self.first, self.last)
person = Person('zhang', 'san')
print(person.fullname)
print(person.last)
print(person.first)
del person.fullname
print(person.last)
print(person.first)

 

四、property()函數原理

使用該函數可以將方法直接變成屬性,與@property類同。

  • 函數接口:property(fget=None, fset=None, fdel=None, doc=None)

使用property的代碼示例:

class Stranger(object):
    def __init__(self, gender=None, age=None, job=None):
        self.gender = gender
        self._age = age
        self.jobb = job
    # 設置_age
    def set_age(self, age):
        if isinstance(age, int):
            self._age = age
        else:
            raise ValueError("'int' type need")
    # 讀取_age
    def get_age(self):
        return self._age
    
    # 使得實例化對象可以利用.age方式來訪問
    age = property(get_age, set_age)
if __name__ == "__main__":
    # 創建一個“妹子”
    meizi = Stranger()
    meizi.age = 18
    print("年齡:{age}".format(age=meizi.age))

# 輸出:
#年齡:18


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved