本篇文章给大家谈谈python典型入门案例,以及python案例讲解视频,希望对各位有所帮助,不要忘了收藏本站喔。
文章结构
- @property由来
- 使用Getter和Setter
- 强大的@property
- 深入Property
Python中@property的强大功能让程序员更优雅的实现何种功能,让我们来认识它吧。
从一个例子说起
假设我们需要设计一个类,能够存储摄氏温度并提供将它转换为华氏温度的方法,你可能会这样做:
class Celsius:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
这看起来完成了我们的需求,我们再来测试下
>>>man=Celsius()
>>>man.temperature=37
>>>man.temperature
37
当我们调用类的属性(比如 temperature
),Python解释器自动寻找类的内置字典 __dict__
>>>man.__dict__
{'_temperature': 23}
man.temperature
自动变成了man.__dict__['temperature']
我在我们假设我们写的代码被很多人引用学了python后还要学c+吗。。。。。
终于有一天,有人使用了下面的命令:
>>>man.temperature=-300
>>>man.temperature
-300
这就尴尬了,我们都知道摄氏温度不能低于-273。而我们写的代码不能阻止这种意外的错误发生,容易发生bug,因此,我们不得不更新代码。
使用Getter和Setter
一个明显的解决方案那就是使用get和set方法对参数进行检查,参考下面代码:
class Celsius2:
def __init__(self, temperature = 0):
self.set_temperature(temperature)
def to_fahrenheit(self):
return (self.get_temperature() * 1.8) + 32
# new update
def get_temperature(self):
return self._temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
self._temperature = value
我们定义了get_temperature
和set_temperature
方法,并进行了参数检查,不允许错误的值被传入。
>>>c=Celsius2(23)
>>>c.get_temperature()
23
>>>c.set_temperature(-300)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-29-57c53727bdf8> in <module>()
----> 1 c.set_temperature(-300)
<ipython-input-8-082673a5adb9> in set_temperature(self, value)
12 def set_temperature(self, value):
13 if value < -273:
---> 14 raise ValueError("Temperature below -273 is not possible")
15 self._temperature = value
ValueError: Temperature below -273 is not possible
这看起来完成了任务,但是。。。。
多出来两个额外的方法,使用者不得不小心翼翼的查阅说明文档,这让代码变得复杂。。
更关键的是,不要忘了,python没有私有变量!!
>>>c._temperature=-300
>>>c.get_temperature()
-300
完了,全TM完了,难道python中就不能让类的属性不轻易的被外部修改?
强大的@property
我们自然有pythonic的方法来达成这种需求
class Celsius3:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
def get_temperature(self):
print("Getting value")
return self._temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self._temperature = value
temperature = property(get_temperature,set_temperature)
我们给每个方法额外的加了一个print函数,以明确每一个命令发生了什么事情。
>>>c3=Celsius3(-20)
Setting value
可以看到,当我们实例化一个类的时候,解释器调用了set_temperature()
方法
>>>c3.temperature
Getting value
-20
>>>c3.temperature=-300
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-40-8d29d5552a4a> in <module>()
----> 1 c3.temperature=-300
<ipython-input-34-f833e358e1ac> in set_temperature(self, value)
12 def set_temperature(self, value):
13 if value < -273:
---> 14 raise ValueError("Temperature below -273 is not possible")
15 print("Setting value")
16 self._temperature = value
ValueError: Temperature below -273 is not possible
>>>c3=Celsius3(-300)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-35-bbb34068b6b0> in <module>()
----> 1 c3=Celsius3(-300)
<ipython-input-34-f833e358e1ac> in __init__(self, temperature)
1 class Celsius3:
2 def __init__(self, temperature = 0):
----> 3 self.temperature = temperature
4
5 def to_fahrenheit(self):
<ipython-input-34-f833e358e1ac> in set_temperature(self, value)
12 def set_temperature(self, value):
13 if value < -273:
---> 14 raise ValueError("Temperature below -273 is not possible")
15 print("Setting value")
16 self._temperature = value
ValueError: Temperature below -273 is not possible
深入理解Property
property()是python的内置函数,创造并返回一个属性对象
property(fget=None, fset=None, fdel=None, doc=None)
temperature = property(get_temperature,set_temperature)
当我们调用c3.temperture
的值的时候,解释器自动调用c3.get_temperature()
同样,当我们使用c3.temperture=-300
的时候,解释器自动调用c3.set_temperature(-300)
最后,为了代码看上去更简洁,python提供了更多的语法糖,我们可以写成这样:
“`
class Celsius:
def init(self, temperature = 0):
self._temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
@property
def temperature(self):
print("Getting value")
return self._temperature
@temperature.setter
def temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self._temperature = value
```