调用@classmethod修饰方法会引发TypeError

时间:2016-12-02 12:42:58

标签: python static-methods read-eval-print-loop class-method

我想弄清楚@staticmethod@classmethod之间的区别。后者传递cls实例。

当我尝试拨打@classmethod时,它给了我一个错误。

如何在REPL中调用@classmethodto_c()to_f())修饰的方法?

这是REPL电话

>>> from temperature_converter import *
>>> c = TemperatureConverter(41)
>>> TemperatureConverter.to_f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Repos\Python\module-3\temperature_converter.py", line 21, in to_f
    return cls.c_to_f(cls.temperature)
  File "C:\Repos\Python\module-3\temperature_converter.py", line 25, in c_to_f
    return celsius * 9 / 5 + 32
TypeError: unsupported operand type(s) for *: 'property' and 'int'

以下是课程TemperatureConverter

class TemperatureConverter:
    _temperature = 0

    @property
    def temperature(self):
        return self._temperature

    @temperature.setter
    def temperature(self, value):
        self._temperature = value

    def __init__(self, temperature):
        self.temperature = temperature

    @classmethod
    def to_c(cls):
        return cls.f_to_c(cls.temperature)

    @classmethod
    def to_f(cls):
        return cls.c_to_f(cls.temperature)

    @staticmethod
    def c_to_f(celsius):
        return celsius * 9 / 5 + 32

    @staticmethod
    def f_to_c(fahrenheit):
        return (fahrenheit - 32) * 5/9

1 个答案:

答案 0 :(得分:1)

问题:您尝试从类中访问ffmpeg('music/ant.mp3') .setStartTime('00:00:03') .setDuration('10') .output('music/ant.mp3') .on('end', function(err) { if(!err) { console.log('conversion Done'); } }) .on('error', function(err){ console.log('error: ', +err); }).run(); 属性并期望与实例具有相同的结果,在这种情况下,temperature值为int }。但是,在实例和类中以不同方式调用属性。比较每个41方法:

<强>描述

__get__

以下是关于# Reassignments for illustration C = TemperatureConverter # class i = c # instance attr = "temperature" # attribute # Call via Instance binding, `c.temperature` C.__dict__[attr].__get__(i, C) # 41 # Call via Class binding, `C.temperature` C.__dict__[attr].__get__(None, C) # <property at 0x4ab9458> 方法签名的information以及关于描述符如何工作的SO post。在这种情况下,签名可以被视为__get__。简而言之,当从属性获取时,与实例调用不同,来自类的调用将C.__get__(self, inst, cls)传递给实例参数

如上所示,如果绑定到类:

,则返回属性对象
None

我们还可以&#34;得到&#34;属性对象的值?让我们在属性对象上调用C.temperature # <property at 0x4ab9458>

__get__

后者表明,绑定到类时可以获取属性值。虽然在类方法中C.temperature.__get__(i, C) # 41 上实现__get__方法可能很诱人,但仍需要传入实例(例如cls.temperature)才能访问财产的价值。在类方法中无法访问实例。因此,我们看到为什么在您的代码中返回属性对象,该代码试图与i相乘并引发您观察到的错误。

这是对您的问题的一种解释,特别是描述了您无法在类方法中访问属性值int的原因。