Python 装饰器之Property: Setter 和Getter
文章推薦指數: 80 %
Unfortunately, it is widespread belief that a proper Python class should encapsulate private attributes by using getters and setters.
Search
AQuestAfterPerspectives
AQuestAfterPerspectives
Home
Projects
Tags
About
Contents
Demo
Case1
Case2
Case3
Case4
Reference
Python装饰器之Property:Setter和Getter
Propertyvs.GetterandSetterinPythondecorators
Herb
Lastupdatedon
Feb15,2021
4minread
Tutorial
Project
Follow
Follow
Getters(alsoknownas‘accessors’)andsetters(aka.‘mutators’)areusedinmanyobjectorientedprogramminglanguagestoensuretheprincipleofdataencapsulation.Dataencapsulation-asyoucanlearninaintroductiononObjectOrientedProgrammingofthetutorial-isseenasthebundlingofdatawiththemethodsthatoperateonthem.Thesemethodsareofcoursethegetterforretrievingthedataandthesetterforchangingthedata.Accordingtothisprinciple,theattributesofaclassaremadeprivatetohideandprotectthemfromtheothercodes.
Unfortunately,itiswidespreadbeliefthataproperPythonclassshouldencapsulateprivateattributesbyusinggettersandsetters.Assoonasoneoftheseprogrammersintroducesanewattribute,heorshewillmakeitaprivatevariableandcreates“automatically”agetterandasetterforthisattributes.SuchprogrammersmayevenuseaneditororanIDE,whichautomaticallycreatesgettersandsettersforallprivateattributes.Thesetoolsevenwarntheprogrammerifsheorheusesapublicattribute!Javaprogrammerswillwrinkletheirbrows,screwuptheirnoses,orevenscreamwithhorrorwhentheyreadthefollowing:ThePythonicwaytointroduceattributesistomakethempublic.
Source:Propertiesvs.GettersandSetters
Using@propertydecoratorstoachievegettersandsettersbehaviour.
Demo
用一个简单例子来开局,体会一般:
classPerson:
def__init__(self,name):
self.name1=name
self.name2='小白'
#利用property装饰器将获取name方法转换为获取对象的属性
@property
defname(self):
returnself.name1+'!'
#利用property装饰器将设置name方法转换为获取对象的属性
@name.setter#@属性名.setter
defname3(self,n):
self.name1='小绿'ifn=='小灰'else'小宝'
p=Person('小黑')
print(p.name,p.name1,p.name2,p.name3)
p.name3='小灰'
print(p.name,p.name1,p.name2,p.name3)
p.name3='小2'
print(p.name,p.name1,p.name2,p.name3)
p.name='123'
Output:
小黑!小黑小白小黑!
小绿!小绿小白小绿!
小宝!小宝小白小宝!
---------------------------------------------------------------------------
AttributeErrorTraceback(mostrecentcalllast)
另外,@name.setter装饰器不仅将调用方法改为了获取指定对象的属性,即p.name3对应于p.name()亦p.name。
此外,对其赋值时相当于调用了方法,即有p.name3=n对应于p.name3(n)。
值得留意的是,上述例子背后其实是在操作私有属性p.name,使用者是透过setter方法来管理输入的值,并对p.name等属性参数进行赋值影响,直接对私有属性p.name进行赋值是不被允许的。
了解了其背后的执行逻辑和规律以后,下面给几个标准写法和实例:
Case1
我们可以用其来对属性的赋值做判断和异常检测。
#Pythonprogramshowingtheuseof
#@propertyfromhttps://www.geeksforgeeks.org/getter-and-setter-in-python/
classGeeks:
def__init__(self):
self._age=0
#usingpropertydecorator
#agetterfunction
@property
defage(self):
print("gettermethodcalled")
returnself._age
#asetterfunction
@age.setter
defage(self,a):
if(a<18):
raiseValueError("Sorryyouageisbeloweligibilitycriteria")
print("settermethodcalled")
self._age=a
Case2
另一种写法就是可以将setter和getter作为私有方法隐藏起来:
#https://www.datacamp.com/community/tutorials/property-getters-setters
classFinalClass:
def__init__(self,var):
##callingtheset_a()methodtosetthevalue'a'bycheckingcertainconditions
self.__set_a(var)
##gettermethodtogetthepropertiesusinganobject
def__get_a(self):
returnself.__a
##settermethodtochangethevalue'a'usinganobject
def__set_a(self,var):
##conditiontocheckwhethervarissuitableornot
ifvar>0andvar%2==0:
self.__a=var
else:
self.__a=2
a=property(__get_a,__set_a)
Case3
这个例子来自stackoverflow上的回答,可以参考其是如何避免delete受保护的属性。
#https://stackoverflow.com/a/36943813/8656360
classProtective(object):
"""protectedpropertydemo"""
#
def__init__(self,start_protected_value=0):
self.protected_value=start_protected_value
#
@property
defprotected_value(self):
returnself._protected_value
#
@protected_value.setter
defprotected_value(self,value):
ifvalue!=int(value):
raiseTypeError("protected_valuemustbeaninteger")
if0<=value<=100:
self._protected_value=int(value)
else:
raiseValueError("protected_valuemustbe"+
"between0and100inclusive")
#
@protected_value.deleter
defprotected_value(self):
raiseAttributeError("donotdelete,protected_valuecanbesetto0")
Output:
>>>p1=Protective(3)
>>>p1.protected_value
3
>>>p1=Protective(5.0)
>>>p1.protected_value
5
>>>p2=Protective(-5)
Traceback(mostrecentcalllast):
File"
FYI:在信号处理中,时域下的采样率sampling_rate,时长time_duration和采样点总数Nt三个变量中是任意两个可以推导出第三个变量。
#https://github.com/stephengreen/lfi-gw/blob/11cd4f650af793db45ebc78892443cc2b0b60f40/lfigw/waveform_generator.py#L250
classDSP():
def__init__(self,):
self.sampling_rate=1024
self.time_duration=8
@property
deff_max(self):
"""Setthemaximumfrequencytohalfthesamplingrate."""
returnself.sampling_rate/2.0
@f_max.setter
deff_max(self,f_max):
self.sampling_rate=2.0*f_max
@property
defdelta_t(self):
return1.0/self.sampling_rate
@delta_t.setter
defdelta_t(self,delta_t):
self.sampling_rate=1.0/delta_t
@property
defdelta_f(self):
return1.0/self.time_duration
@delta_f.setter
defdelta_f(self,delta_f):
self.time_duration=1.0/delta_f
@property
defNt(self):
returnint(self.time_duration*self.sampling_rate)
@property
defNf(self):
returnint(self.f_max/self.delta_f)+1
defOUTPUT():
print('-'*20+'''\nsampling_rate:{}
time_duration:{}
f_max:{}
delta_t:{}
delta_f:{}
Nt:{}
Nf:{}\n'''.format(t.sampling_rate,t.time_duration,t.f_max,t.delta_t,t.delta_f,t.Nt,t.Nf)+'-'*20)
Output:
>>>t=DSP()
>>>OUTPUT()
--------------------
sampling_rate:1024
time_duration:8
f_max:512.0
delta_t:0.0009765625
delta_f:0.125
Nt:8192
Nf:4097
--------------------
>>>t.f_max=256
>>>OUTPUT()
--------------------
sampling_rate:512.0
time_duration:8
f_max:256.0
delta_t:0.001953125
delta_f:0.125
Nt:4096
Nf:2049
--------------------
>>>t.delta_t=1/8192
>>>OUTPUT()
--------------------
sampling_rate:8192.0
time_duration:8
f_max:4096.0
delta_t:0.0001220703125
delta_f:0.125
Nt:65536
Nf:32769
--------------------
Reference
此文探讨非常浅显,仅简明扼要,更多的讨论素材和教程细节,可参阅下方的参考文献:
property和setter装饰器-cnblogs
[Python]setter和getter
Propertiesvs.GettersandSetters
Python@propertydecorator-Programiz
Propertyvs.GettersandSettersinPython
GetterandSetterinPython
AGreatAnswerfor“What’sthepythonicwaytousegettersandsetters?”-stackoverflow
ThePythonStandardLibrary-Built-inFunctions-classproperty
Python
SignalProcessing
Next
Unit3:Structure&Paragraphs(学术写作)
Previous
Unit2:Verbs(学术写作)
Related
谱分析(spectralanalysis)的SciPy代码解析
Python中负数取余问题
恒Q变换(Constant-Qtransform)
S变换(Stockweltransform)
傅里叶变换算法及其python实现
Cite
×
Copy
Download
延伸文章資訊
- 1[Python教學]@property是什麼? 使用場景和用法介紹
Python內建的@property 用法,本篇描述了property 的兩種特性,和一個實際 ... 接下來我們會在特性二看到property 的setter、getter 和deleter ...
- 2[Python] setter 和getter. 從鋼彈學python 第一彈 - Medium
從鋼彈學python 第一彈. “[Python] setter 和getter” is published by Bryan Yang in 亂點技能的跨界人生.
- 3Getter and Setter in Python - GeeksforGeeks
In Python, getters and setters are not the same as those in other object-oriented programming lan...
- 4Python 慣用語- 14 用property 取代getters, setters
寫Java 的人習慣寫一堆getX() 以及setX(),這在Python 中是不被鼓勵的,pythonic 方式是直接存取attribute ,而當你需要進一步控制時,可以使用pr...
- 5What's the pythonic way to use getters and setters? - Stack ...
Try this: Python Property. The sample code is: class C(object): def __init__(self): self._x = Non...