【问题标题】:Calling a method within another method in the context of @property在 @property 的上下文中调用另一个方法中的方法
【发布时间】:2013-08-15 13:30:28
【问题描述】:

使用以下包含@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。我想在grade() 中调用failure() 以避免此错误。

有一个实例:

g = Grade_Calculator(89)

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

我看到很多关于只是进行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

我不明白什么?

【问题讨论】:

    标签: python oop methods decorator


    【解决方案1】:

    您已将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()
    

    【讨论】:

    • "您已将故障定义为属性。因此,您不能使用 () 表示法来调用它;事实上,不这样做是使用属性的全部意义所在。"...对我来说灯泡时刻 - 谢谢。尽管@Paco's 也很好,但由于回答的彻底性而被接受。
    【解决方案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
    

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

    【讨论】:

      猜你喜欢
      • 2021-08-31
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 1970-01-01
      • 2015-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多