Maison  >  Article  >  développement back-end  >  Existe-t-il un décorateur équivalent à « @property » en Python pour définir une propriété de classe ?

Existe-t-il un décorateur équivalent à « @property » en Python pour définir une propriété de classe ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-11-11 00:52:03579parcourir

Is there a decorator equivalent to `@property` in Python for defining a class property?

Comment définir une propriété de classe en Python

En Python, le décorateur @classmethod peut être utilisé pour ajouter une méthode à une classe. Cependant, existe-t-il un décorateur équivalent pour définir une propriété pour une classe ?

Décorateur de propriété de classe

Pour répondre à cette question, considérons l'exemple suivant :

class Example(object):
    the_I = 10

    def __init__(self):
        self.an_i = 20

    @property
    def i(self):
        return self.an_i

    def inc_i(self):
        self.an_i += 1

    # is this even possible?
    @classproperty
    def I(cls):
        return cls.the_I

    @classmethod
    def inc_I(cls):
        cls.the_I += 1

e = Example()
assert e.i == 20
e.inc_i()
assert e.i == 21

assert Example.I == 10
Example.inc_I()
assert Example.I == 11

Dans cet exemple, l'intention est de définir une propriété de classe I à l'aide du décorateur @classproperty. Cependant, l'erreur "NameError : le nom 'classproperty' n'est pas défini" est générée.

Solution

Pour créer une propriété de classe, une classe de descripteur personnalisée appelée ClassPropertyDescriptor peut être utilisé :

import inspect

class ClassPropertyDescriptor(object):

    def __init__(self, fget, fset=None):
        self.fget = fget
        self.fset = fset

    def __get__(self, obj, klass=None):
        if klass is None:
            klass = type(obj)
        return self.fget.__get__(obj, klass)()

    def __set__(self, obj, value):
        if not self.fset:
            raise AttributeError("can't set attribute")

        if inspect.isclass(obj):
            type_ = obj
            obj = None
        else:
            type_ = type(obj)

        return self.fset.__get__(obj, type_)(value)

    def setter(self, func):
        if not isinstance(func, (classmethod, staticmethod)):
            func = classmethod(func)
        self.fset = func
        return self

La classe ClassPropertyDescriptor définit le comportement de la propriété de classe. Il implémente les méthodes __get__ et __set__ pour gérer l'obtention et la définition de la valeur de la propriété.

Décorateur de propriété de classe

Pour faciliter l'utilisation du descripteur de propriété de classe, un décorateur appelé @ classproperty peut être créé :

def classproperty(func):
    if not isinstance(func, (classmethod, staticmethod)):
        func = classmethod(func)

    return ClassPropertyDescriptor(func)

Exemple d'utilisation

Avec le descripteur et le décorateur de propriété de classe personnalisés en place, l'exemple peut être réécrit comme :

class Bar(object):

    _bar = 1

    @classproperty
    def bar(cls):
        return cls._bar

    @bar.setter
    def bar(cls, value):
        cls._bar = value

Ce code définit une barre de propriétés de classe accessible et modifiable comme prévu. La modification de la valeur de la propriété sur l'instance de classe ou sur la classe elle-même mettra à jour la valeur de toutes les instances 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