Maison >développement back-end >Tutoriel Python >Pourquoi ne puis-je pas utiliser `property()` avec Classmethods en Python et quelles sont les solutions de contournement ?

Pourquoi ne puis-je pas utiliser `property()` avec Classmethods en Python et quelles sont les solutions de contournement ?

DDD
DDDoriginal
2024-12-12 21:28:12267parcourir

Why Can't I Use `property()` with Classmethods in Python, and What Are the Workarounds?

Utilisation de property() avec classmethod : une exploration

En Python, la fonction property() joue un rôle crucial dans la création de getters et de setters pour les attributs de classe. Cependant, tenter d'utiliser property() avec des méthodes de classe, qui sont décorées avec le décorateur @classmethod, peut entraîner des erreurs inattendues.

Considérons l'extrait de code suivant qui illustre le problème :

class Foo(object):
    _var = 5

    @classmethod
    def getvar(cls):
        return cls._var

    @classmethod
    def setvar(cls, value):
        cls._var = value

    var = property(getvar, setvar)

Lorsque nous essayons d'accéder ou de définir l'attribut var sur une instance de la classe Foo, nous rencontrons un erreur :

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

Comme expliqué dans la documentation et dans les discussions sur le débordement de pile [Méthode de classe Python en tant que Setter et Getter](https://stackoverflow.com/questions/27906399/python-class-method-as -setter-and-getter), il n'est pas possible d'utiliser la fonction property() avec les méthodes de classe en Python 3.8 et plus tôt.

Cependant, il existe des approches alternatives pour obtenir la fonctionnalité souhaitée :

Pour Python 2 et Python 3 (y compris 3.9-3.10) :

Puisqu'une propriété affecte une instance, mais qu'une propriété de classe est créée sur la classe, il est nécessaire de créer la propriété sur la métaclasse.

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)

Pour les versions Python à partir de 3.9 :

Une solution plus propre consiste à déplacer les méthodes de classe vers la métaclasse et à déclarer la propriété directement sur la métaclasse :

class Foo_meta(type):
    @property
    def var(cls):
        return cls._var

    @var.setter
    def var(cls, value):
        cls._var = value

class Foo(metaclass=Foo_meta):
    _var = 5

Ces méthodes alternatives permettent effectivement d'utiliser des propriétés au niveau de la classe.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn