python - 属性() 在 Class 使用问题中,setter 显示 TypeError

python - property() in a Class use problem, setter shows TypeError

我正在 codechalleng.es 上编写一个 pybite,完全 运行 没有想法。 问题如下: task description

我需要写一个 class returns 布尔值 True/False 促销是否已过期。 它通过调用 属性 getter promotion.expired 进行测试(请参阅最后的测试)

from datetime import datetime, timedelta

NOW = datetime.now()    # defined here for test compatilibity (time)

class Promo:
    """ docstring hehe"""

    def __init__(self, name, expires):
        self.name = name
        self.setpromo(expires)


    def checkpromo(self):
        return self.expired

    def setpromo(self, value):
        self.expired = value < datetime.now()

    expired = property(checkpromo, setpromo)


test_time = NOW + timedelta(days=1)

promotion_10 = Promo('promotion 10%', test_time)

现在它抛出一个错误,我无法比较 setter 与 datetime 对象中的值。在我看来,当我们将 test_time(日期时间对象)传递给 setter 时,它应该能够比较日期时间与日期时间——相反,程序说它是一个布尔值。不确定如何进行。感谢您的任何见解。

Traceback (most recent call last):
  File "/tmp/simple_property.py", line 24, in <module>
promotion_10 = Promo('promotion 10%', test_time)
  File "/tmp/simple_property.py", line 10, in __init__
self.setpromo(expires)
  File "/tmp/simple_property.py", line 17, in setpromo
self.expired = value < datetime.now()
  File "/tmp/simple_property.py", line 17, in setpromo
self.expired = value < datetime.now()
TypeError: '<' not supported between instances of 'bool' and 'datetime.datetime'  

需要通过的测试:

from datetime import timedelta
import inspect

from simple_property import Promo, NOW


def test_promo_expired():
    past_time = NOW - timedelta(seconds=3)
    twitter_promo = Promo('twitter', past_time)
    assert twitter_promo.expired


def test_promo_not_expired():
    future_date = NOW + timedelta(days=1)
    newsletter_promo = Promo('newsletter', future_date)
    assert not newsletter_promo.expired


def test_uses_property():
    assert 'property' in inspect.getsource(Promo)

我终于找到了问题 - 遇到这种 setter/property() 行为的人可能会感兴趣。 (如果我不应该回答我自己的 question/close 主题等,请纠正我)

在我的示例中,属性 expired 与私有属性 self.expired.

将代码更改为(只需在 self._expired 中添加一个下划线 - 更改名称使其不与 属性() 名称重叠):

def checkpromo(self):
    return self._expired

def setpromo(self, value):
    self._expired = value < datetime.now()

成功了!谢谢

编辑 - 添加优雅的装饰器方法来解决任务(将我的任务提交给 codechalleng.es 后作为答案提供)

from datetime import datetime

NOW = datetime.now()


class Promo:

    def __init__(self, name, expires=NOW):
        self.name = name
        self.expires = expires

    @property
    def expired(self):
        return datetime.now() > self.expires