python - How to make a class property? -


this question has answer here:

in python can add method class @classmethod decorator. there similar decorator add property class? can better show i'm talking about.

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     # 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 

is syntax i've used above possible or require more?

the reason want class properties can lazy load class attributes, seems reasonable enough.

here's how this:

class classpropertydescriptor(object):      def __init__(self, fget, fset=none):         self.fget = fget         self.fset = fset      def __get__(self, obj, klass=none):         if klass 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)   class bar(object):      _bar = 1      @classproperty     def bar(cls):         return cls._bar      @bar.setter     def bar(cls, value):         cls._bar = value   # test instance instantiation foo = bar() assert foo.bar == 1  baz = bar() assert baz.bar == 1  # test static variable baz.bar = 5 assert foo.bar == 5  # test setting variable on class bar.bar = 50 assert baz.bar == 50 assert foo.bar == 50 

the setter didn't work @ time call "bar.bar", because calling "typeofbar.bar.__set__", not "bar.bar.__set__", add metaclass define solve it

class classpropertymetaclass(type):     def __setattr__(self, key, value):         if key in self.__dict__:         obj = self.__dict__.get(key)         if obj , type(obj) classpropertydescriptor:             return obj.__set__(self, value)          return super(classpropertymetaclass, self).__setattr__(key, value)  # , update class define: #     class bar(object): #        __metaclass__ = classpropertymetaclass #        _bar = 1  # , update classpropertydescriptor.__set__ #    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) 

now fine


Comments

Popular posts from this blog

c# - How to set Z index when using WPF DrawingContext? -

razor - Is this a bug in WebMatrix PageData? -

visual c++ - Using relative values in array sorting ( asm ) -