クラスメソッドで property() を使用する 質問する

クラスメソッドで property() を使用する 質問する

classmethod()本質的に静的変数を取得および設定するための2 つのクラス メソッド (関数を使用) を持つクラスがあります。property()これらで関数を使用しようとしましたが、エラーが発生しました。インタープリターで次のようにしてエラーを再現できました。

class Foo(object):
    _var = 5
    @classmethod
    def getvar(cls):
        return cls._var
    @classmethod
    def setvar(cls, value):
        cls._var = value
    var = property(getvar, setvar)

クラスメソッドをデモンストレーションすることはできますが、プロパティとしては機能しません。

>>> f = Foo()
>>> f.getvar()
5
>>> f.setvar(4)
>>> f.getvar()
4
>>> f.var
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable
>>> f.var=5
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable

装飾された関数property()で関数を使用することは可能ですか?@classmethod

ベストアンサー1

3.8 < Python < 3.11

両方のデコレータを一緒に使用できます。この答え

Python 2 および Python 3 (3.9-3.10 でも動作します)

プロパティはクラス上に作成されますが、インスタンスに影響します。したがって、プロパティが必要な場合はclassmethod、メタクラス上にプロパティを作成します。

>>> class foo(object):
...     _var = 5
...     class __metaclass__(type):  # Python 2 syntax for metaclasses
...         pass
...     @classmethod
...     def getvar(cls):
...         return cls._var
...     @classmethod
...     def setvar(cls, value):
...         cls._var = value
...     
>>> foo.__metaclass__.var = property(foo.getvar.im_func, foo.setvar.im_func)
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3

しかし、いずれにせよメタクラスを使用しているので、クラスメソッドをそこに移動すると読みやすくなります。

>>> class foo(object):
...     _var = 5
...     class __metaclass__(type):  # Python 2 syntax for metaclasses
...         @property
...         def var(cls):
...             return cls._var
...         @var.setter
...         def var(cls, value):
...             cls._var = value
... 
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3

または、Python 3 のmetaclass=...構文を使用し、クラス本体の外部で定義されたメタクラスfooと、の初期値を設定するメタクラスを使用します_var

>>> class foo_meta(type):
...     def __init__(cls, *args, **kwargs):
...         cls._var = 5
...     @property
...     def var(cls):
...         return cls._var
...     @var.setter
...     def var(cls, value):
...         cls._var = value
...
>>> class foo(metaclass=foo_meta):
...     pass
...
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3

おすすめ記事