nestarz
nestarz

Reputation: 119

How to apply properties on classmethod?

My question is simple: How can I add properties and setter to classmethod ?

Here is my code:

class Ingredient():
     __max_stock = 100
     __stock = 0
     __prix = 0

     def __init__(self):
         pass

     @classmethod
     @property
     def prix(cls):
         return cls.__prix
     @classmethod
     @prix.setter
     def prix(cls, value):
         assert isinstance(value, int) and int(abs(value)) == value
         cls.__prix = value


Ingredient.prix = 10        #should be OK
Ingredient.prix = 'text'    #should raise an error
Ingredient.prix = 10.5      #should raise an error too

Problem is that the setter doesn't work when the var is a class variable. Here is the error I get :

AttributeError: 'classmethod' object has no attribute 'setter'

I use Python 3.x

Upvotes: 0

Views: 5223

Answers (2)

spacether
spacether

Reputation: 2699

This is possible in python >= 3.9 per https://docs.python.org/3/howto/descriptor.html#id27 See For example, a classmethod and property could be chained together

You may have a use case where you only want to calculate a classmethod property one time then keep using that value. If that is the case and this calculation needs to be done on subclasses, one could use init_subclass in python >= 3.6 to do this

class A:
    @classmethod
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.prix = cls._prix

class B(A):
    _prix = 0

Upvotes: 2

mvr
mvr

Reputation: 611

Don't use classmethod directly in this way. If you need a classproperty decorator that is analogous to the instance property decorator including the possibility of setters, check out other questions for some good patterns. (You could also do it with a metaclass, but there's probably no reason to get into that.)

Upvotes: 1

Related Questions