2016-12-02 17 views
0

@staticmethod@classmethodの違いを把握しようとしています。後者にはclsインスタンスが渡されます。@classmethodデコレートされたメソッドを呼び出すと、TypeErrorがスローされます

@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

あなたがしようとしていることは意味をなさない。 'cls.temperature'は、値を持つインスタンスではなく、記述子オブジェクト自体を参照します。クラスメソッドも静的メソッドも、すべてのインスタンス値にアクセスすることはできません。 –

+1

'to_c'と' to_f'をclassmethodsにしたいのはなぜですか?彼らが変換しようとしている可能性が高い温度は、その名前のclass属性が常に '0'であるため、' _temperature'インスタンス属性です(引数を与えるために定義を変更しない場合)。非常にインスタンスが(プロパティを介して)コンストラクタによって割り当てられた値を取得するので、class属性はデフォルト値としても必要ありません。 – Blckknght

答えて

1

問題です:あなたはクラスから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> 
__get__メソッドのシグネチャにここ

でよりinformationと記述子がどのように機能するかについてSO post。この場合、署名はC.__get__(self, inst, cls)と見なすことができます。要するに、プロパティから取得する場合、はインスタンスコールと異なり、クラスからの呼び出しはのインスタンス引数Noneを渡します。

上記のようにクラスにバインドされている場合、プロパティのオブジェクトが返されます。

C.temperature 
# <property at 0x4ab9458> 

我々はまだプロパティオブジェクトから値を「取得」することはできますか?私たちは、プロパティオブジェクトに__get__を呼ぶことにしましょう:

C.temperature.__get__(i, C) 
# 41 

後者は、クラスにバインドしながら、プロパティの値を取得することも可能であることを示しています。クラスメソッド内でcls.temperature__get__メソッドを実装することが魅力的かもしれませんが、のインスタンスには(たとえばi)のインスタンスを渡す必要があります。インスタンスはクラスメソッドではアクセスできません。このため、コード内でプロパティオブジェクトが返され、intで乗算しようとしているエラーが発生するのがわかります。

これは問題の説明の1つで、特にクラスメソッド内でプロパティ値cls.temperatureにアクセスできない理由を説明しています。

+1

ああ、何らかの理由で、私はクラスオブジェクトの 'インスタンス'が 'cls'を介して' to_c(cls) 'に渡されていると考えました。私は間違っていた...ありがとう、啓蒙のための@pylang – Sung

関連する問題