目錄
1. property裝飾器的基本用法
2. property裝飾器的原理
3. 讓屬性可寫、可洗掉
4. 獲得原始方法
1. property裝飾器的基本用法
在講property裝飾器之前,先來看一個例子:
class MyClass:
def __init__(self, word):
self._word = word
def word(self):
return self._word
my = MyClass('Hello')
print(my.word())
print(my.word)
執行這段代碼,會輸出如下的結果:
Hello
<bound method MyClass.word of <__main__.MyClass object at 0x7fee500b61f0>>
這段代碼的主要功能就是通過word方法回傳一個字串,而最后一行直接訪問了word方法,在Python語言中,任何東西都可視為物件,方法也不例外,所以直接輸出了word方法的物件形式,
不過my.word這種呼叫形式,其實也是訪問屬性的方式,所以這段代碼也可以看做將word方法作為屬性使用,而不是獲取word物件本身,因此,如果要想將word方法作為屬性使用,就要使用property裝飾器,下面看一下改進的代碼:
class MyClass:
def __init__(self, word):
self._word = word
# 將word方法變成屬性
@property
def word(self):
return self._word
my = MyClass('Hello')
# 輸出Hello
print(my.word)
這段代碼使用@property修飾了word方法,這時就會將word方法直接變成了屬性,所以可以使用my.word形式呼叫word方法,運行這段代碼,會輸出Hello,
我們可以看到,只需要1行代碼,就可以將任何一個普通的Python方法變成屬性,
如果用@property修飾方法,那么就不能再當做方法呼叫了,例如,不能再使用my.word()形式呼叫word方法了,否則會拋出如下例外:

2. property裝飾器的原理
可能有很多小伙伴感到很神奇,為何直接用@property修飾方法,就可以將Python方法變成屬性呢?本節就來詳細描述property裝飾器的原理,

首先要了解property到底是什么,使用下面的代碼輸出property:
print(property)
輸出結果如下:
<class 'property'>
很明顯,property是一個類,而Python裝飾器其實就是一個語法糖,本質上是將Python裝飾器作為函式使用,并將被修飾器修飾的方法/函式作為引數值傳入裝飾器函式,例如,使用@property裝飾word方法,那么就相當于使用下面的代碼包裝word方法:
property(word)
也就是說,word方法被@property修飾后,就會變成property類的實體,
可以用下面的代碼來演示property裝飾器的原理,在這段代碼中,使用@property修飾了word方法,而new_word方法直接通過創建property實體的方式修飾,
class MyClass:
def __init__(self, word):
self._word = word
@property
def word(self):
return self._word
# 輸出被修飾的word方法的型別
print('word:', type(word))
def new_word(self):
return self._word
# 輸出未被修飾的new_word方法的型別
print('new_word:', type(new_word))
new_word = property(new_word)
print(type(new_word))
my = MyClass("android")
print(my.word)
print(my.new_word)
執行這段代碼,會輸出如下內容:

從輸出結果可以看出,被@property修飾的word方法的型別是property類,而未被@property修飾的new_word方法的型別是function類,而且通過創建property實體的方式包裝的new_word方法也可以當做屬性使用,與下面的代碼等效:
@property
def new_word(self):
return self._word
3. 讓屬性可寫、可洗掉
用@property修飾的方法是只讀屬性,既不可以寫,也不可以洗掉,否則會拋出例外,
如果使用my.word = 'new'設定word屬性,會拋出如下例外,

如果使用del my.word洗掉word屬性,會拋出如下例外:

其實property類還有setter方法和deleter方法,可以將屬性變成可寫和可洗掉的,先看下面的代碼:
class MyClass:
def __init__(self, word):
self._word = word
@property
def word(self):
return self._word
# 設定可寫屬性
@word.setter
def word(self, value):
self._word = value
# 設定可洗掉屬性,洗掉word屬性時會呼叫該方法
@word.deleter
def word(self):
print('delete word')
self._word = ''
# 通過創建property實體的方式將new_word方法變成可讀寫和可洗掉的
def new_word(self):
return self._word
# 將new_word變成只讀的屬性,并且需要將property實體賦給一個新的變數,否則會被后面的new_word方法覆寫
new_word1 = property(new_word)
def new_word(self, value):
self._word = value
# 將new_word變成可寫的屬性
new_word1 = new_word1.setter(new_word)
def new_word(self):
print('delete new word')
# 將new_word變成可洗掉的屬性
new_word = new_word1.deleter(new_word)
my = MyClass('hello')
print(my.word)
my.word = 'world' # def word(self, value):
print(my.word)
del my.word
print(my.word)
print('---------')
my = MyClass('ios')
print(my.new_word)
my.new_word = 'harmony'
print(my.new_word)
del my.new_word
print(my.new_word)
執行這段代碼啊,會輸出如下內容:

4. 獲得原始方法
用@property修飾的方法,就會被property實體取代,那么如何獲取原始的方法呢?這就要通過property類的如下3個方法:
(1)fget:獲取被@property或@property.getter修飾的方法
(2)fset:獲取被@property.setter修飾的方法
(3)fdel:獲取被@property.deleter修飾的方法
在下面的例子中,分別獲取了word屬性的3個原始方法,并且呼叫了這3個原始方法
class MyClass:
def __init__(self, word):
self._word = word
@property
def word(self):
return self._word
@word.setter
def word(self, value):
self._word = value
@word.deleter
def word(self):
print('delete word')
self._word = ''
fget_word = word.fget
fset_word = word.fset
fdel_word = word.fdel
my = MyClass('android')
print(my.fget_word())
my.fset_word('harmony')
print(my.fget_word())
print(my.fdel_word())
執行這段代碼,會輸出如下的結果,

Ω
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/277038.html
標籤:python
