python - How to make a class property? -
this question has answer here:
- using property() on classmethods 14 answers
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
Post a Comment