繁体   English   中英

使用双星号(**)实现属性

[英]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

据我所知, fgetfset是关键字参数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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM