0

使用以下包含 @property 装饰器的示例代码:

class Grade_Calculator(object):
    def __init__(self,score):
        self.score = score

    @property
    def grade(self):
        if self.score in range(60,70):
            grade = 'D'
        elif self.score in range(70,80):
            grade = 'C'
        elif self.score in range(80,90):
            grade = 'B'
        elif self.score in range(90,101):
            grade = 'A'
        return grade

    @property
    def failure(self):
        if self.score < 60:
            print 'See me'
            grade = 'F'
            return grade

和一个例子:

g = Grade_Calculator(28)

g.grade返回一个UnboundLocalError. 我想打电话来避免这个错误failure()grade()

有一个实例:

g = Grade_Calculator(89)

g.failure()默默地失败。在这种情况下,我想grade()在内部调用failure()以充当故障保险。

我已经看到很多关于只是self.method()打电话的参考资料,但它们对我不起作用,我认为装饰器的存在以某种方式把我搞砸了:

@property
def grade(self):
    if self.score < 60:
        self.failure()
    elif self.score in range(60,70):
        grade = 'D'
    elif self.score in range(70,80):
        grade = 'C'
    elif self.score in range(80,90):
        grade = 'B'
    elif self.score in range(90,101):
        grade = 'A'
    return grade

g = Grade_Calculator(28)
g.grade
See me
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-667-fb10e6cf27d4> in <module>()
----> 1 g.grade

./sample.py in grade(self)
      6     def grade(self):
      7         if self.score < 60:
----> 8             self.failure()
      9         elif self.score in range(60,70):
     10             grade = 'D'

TypeError: 'str' object is not callable

我不明白什么?

4

2 回答 2

2
class Grade_Calculator(object):
    def __init__(self, score):
        self.score = score

    @property
    def grade(self):
        grade = self.failure
        if 60 <= self.score < 70:
            grade = 'D'
        elif 70 <= self.score < 80:
            grade = 'C'
        elif 80 <= self.score < 90:
            grade = 'B'
        elif 90 <= self.score < 100:
            grade = 'A'
        return grade

    @property
    def failure(self):
        if self.score < 60:
            print 'See me'
            grade = 'F'
            return grade

if __name__ == '__main__':
    a = Grade_Calculator(71)
    print a.grade

您基本上是使用 failure 方法为您的对象创建一个新属性。而且你永远不会试图获得它的价值,这就是为什么你永远不会看到'See me' 顺便说一句,你正在覆盖最初是整数的等级值。您将其转换为字符串 ( 'A', 'B', 'C', ...) 我提供的代码有效,但我更改了一些内容。无需调用范围(这很昂贵)。你可以value < variable < other_value在 Python中使用

于 2013-08-13T19:41:33.010 回答
2

您已定义failure为属性。因此,您不能使用()符号来调用它;事实上,不这样做是使用属性的全部意义所在。self.failure返回'F',然后您尝试调用它,这就是为什么您收到有关无法调用字符串的错误的原因。就好像你写'F'()的是一个明显的错误。

此外,您正在丢弃您从中获得的价值,failure并且您只会在失败的情况下返回一个价值(这意味着您会获得None其他价值)。当然,您只有failure在开始时成绩不及格时才能访问...在这种情况下,您不需要检查内部情况failure,现在是吗?

此外,在属性中打印东西是非常糟糕的风格。当您访问属性时,您不会期望打印某些内容。关注点分离:类之外的东西可能应该进行打印,或者你应该有一个单独的方法来调用打印返回的任何内容grade

我会重写你的类如下:

class Grade_Calculator(object):
    def __init__(self, score):
        self.score = score

    @property
    def grade(self):
        if self.failure:
            return 'F'
        if 60 <= self.score < 70:
            return 'D'
        if 70 <= self.score < 80:
            return 'C'
        if 80 <= self.score < 90:
            return 'B'
        if 90 <= self.score < 100:
            return 'A'

    @property
    def failure(self):
        return self.score < 60   # returns True or False

    def print_grade(self):
        print self.grade, "- see me" * self.failure

if __name__ == '__main__':
    c = Grade_Calculator(71)
    c.print_grade()
于 2013-08-13T19:50:02.367 回答