[英]Implementing a property using the double asterisk (**)
在http://www.programiz.com/python-programming/property之后,我熟悉以下在Python中实现属性的方法:
class Celsius(object):
def __init__(self, temperature = 0):
self._temperature = temperature
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)
我现在正在阅读一些代码,其中使用双星号( **
)来定义属性。 如果我将其调整为适合自己的示例,则它看起来像这样:
class Celsius(object):
def __init__(self, temperature = 0):
self._temperature = temperature
def temperature():
def fget(self):
print("Getting value")
return self._temperature
def fset(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self._temperature = value
temperature = property(**temperature())
但是,如果我尝试运行此代码并通过c = Celsius()
实例化一个类,则会得到
TypeError: type object argument after ** must be a mapping, not NoneType
据我所知, fget
和fset
是关键字参数property
,所以我希望什么出来的**temperature()
是像fget=fget, fset=fset
,但我不知道这到底是怎么还是走错了如何进一步剖析。 有任何想法吗?
您应该return
嵌套函数,然后根据函数调用将其解压缩:
class Celsius(object):
def __init__(self, temperature = 0):
self._temperature = temperature
def temperature():
...
return fget, fset
temperature = property(*temperature())
如果您坚持使用**
,那么您将从函数中返回映射/字典,然后将其解压缩为关键字参数。
def temperature():
...
return {'fget': fget, 'fset': fset}
temperature = property(**temperature())
之所以会出现此错误,是因为temperature()
调用返回None
,然后您尝试使用**
将其解包为字典。 因此,要使该代码正常工作,您需要返回一个包含setter和getter方法的适当字典。
我更喜欢Moses的解决方案,但是如果您确实愿意, 可以使用dict而不是元组传递方法。 例如,
class Celsius(object):
def __init__(self, temperature = 0):
self._temperature = temperature
def temperature():
def fget(self):
print("Getting value")
return self._temperature
def fset(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self._temperature = value
return {'fget': fget, 'fset': fset}
temperature = property(**temperature())
# Test
a = Celsius()
a.temperature = 20
print(a.temperature)
产量
Setting value
Getting value
20
确实,我错过了temperature
函数定义中的return
语句。 原始代码实际上包含该行
return locals()
添加此行使该属性按预期工作。
您定义的temperature
方法没有return语句,因此它隐式返回None
,这是错误消息中的...,not NoneType
。 该方法确实有两个子方法,但是这不会导致它以任何形式返回它们,我认为您缺少诸如(untested)之类的行:
return { "fget": fget, "fset": fset }
您还可以使用一个列表和一个*
。
话虽如此,这是避免*
和**
魔术的最佳实践,也有防止这种情况的柔道规则 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.