Les propriétés de classe peuvent-elles être définies avec un décorateur en Python ?

DDD
Libérer: 2024-11-11 04:08:03
original
931 Les gens l'ont consulté

Can Class Properties Be Defined With a Decorator in Python?

Propriétés de classe en Python

En Python, des méthodes de classe peuvent être ajoutées à l'aide du décorateur @classmethod. Mais qu’en est-il des propriétés de classe ? Y a-t-il un décorateur pour eux ?

Considérez ce code :

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
Copier après la connexion

Le code définit un exemple de classe avec une propriété d'instance i, une propriété de classe I et deux méthodes de classe inc_i et inc_I .

Cependant, la syntaxe utilisée pour @classproperty n'est pas correcte en Python. Pour créer une propriété de classe, nous pouvons utiliser l'approche suivante :

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")
        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

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

    return ClassPropertyDescriptor(func)
Copier après la connexion

Avec ce code d'assistance, nous pouvons définir les propriétés de classe comme suit :

class Bar(object):

    _bar = 1

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

    @bar.setter
    def bar(cls, value):
        cls._bar = value
Copier après la connexion

Le décorateur classproperty crée un descripteur qui gère les opérations get et set pour la propriété de classe.

En ajoutant une définition de métaclasse, nous pouvons également gérer la définition de la propriété de classe directement sur la classe :

class ClassPropertyMetaClass(type):
    def __setattr__(self, key, value):
        if key in self.__dict__:
            obj = self.__dict__.get(key)
        if obj and type(obj) is ClassPropertyDescriptor:
            return obj.__set__(self, value)

        return super(ClassPropertyMetaClass, self).__setattr__(key, value)

Bar.__metaclass__ = ClassPropertyMetaClass
Copier après la connexion

Maintenant, les deux instances et les propriétés de classe peuvent être utilisées et définies comme prévu.

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!

source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal