Using property() on classmethods

后端 未结 15 761
Happy的楠姐
Happy的楠姐 2020-11-22 16:55

I have a class with two class methods (using the classmethod() function) for getting and setting what is essentially a static variable. I tried to use the property() functi

相关标签:
15条回答
  • 2020-11-22 17:49

    Half a solution, __set__ on the class does not work, still. The solution is a custom property class implementing both a property and a staticmethod

    class ClassProperty(object):
        def __init__(self, fget, fset):
            self.fget = fget
            self.fset = fset
    
        def __get__(self, instance, owner):
            return self.fget()
    
        def __set__(self, instance, value):
            self.fset(value)
    
    class Foo(object):
        _bar = 1
        def get_bar():
            print 'getting'
            return Foo._bar
    
        def set_bar(value):
            print 'setting'
            Foo._bar = value
    
        bar = ClassProperty(get_bar, set_bar)
    
    f = Foo()
    #__get__ works
    f.bar
    Foo.bar
    
    f.bar = 2
    Foo.bar = 3 #__set__ does not
    
    0 讨论(0)
  • 2020-11-22 17:52

    After searching different places, I found a method to define a classproperty valid with Python 2 and 3.

    from future.utils import with_metaclass
    
    class BuilderMetaClass(type):
        @property
        def load_namespaces(self):
            return (self.__sourcepath__)
    
    class BuilderMixin(with_metaclass(BuilderMetaClass, object)):
        __sourcepath__ = 'sp'        
    
    print(BuilderMixin.load_namespaces)
    

    Hope this can help somebody :)

    0 讨论(0)
  • 2020-11-22 17:53

    There is no reasonable way to make this "class property" system to work in Python.

    Here is one unreasonable way to make it work. You can certainly make it more seamless with increasing amounts of metaclass magic.

    class ClassProperty(object):
        def __init__(self, getter, setter):
            self.getter = getter
            self.setter = setter
        def __get__(self, cls, owner):
            return getattr(cls, self.getter)()
        def __set__(self, cls, value):
            getattr(cls, self.setter)(value)
    
    class MetaFoo(type):
        var = ClassProperty('getvar', 'setvar')
    
    class Foo(object):
        __metaclass__ = MetaFoo
        _var = 5
        @classmethod
        def getvar(cls):
            print "Getting var =", cls._var
            return cls._var
        @classmethod
        def setvar(cls, value):
            print "Setting var =", value
            cls._var = value
    
    x = Foo.var
    print "Foo.var = ", x
    Foo.var = 42
    x = Foo.var
    print "Foo.var = ", x
    

    The knot of the issue is that properties are what Python calls "descriptors". There is no short and easy way to explain how this sort of metaprogramming works, so I must point you to the descriptor howto.

    You only ever need to understand this sort of things if you are implementing a fairly advanced framework. Like a transparent object persistence or RPC system, or a kind of domain-specific language.

    However, in a comment to a previous answer, you say that you

    need to modify an attribute that in such a way that is seen by all instances of a class, and in the scope from which these class methods are called does not have references to all instances of the class.

    It seems to me, what you really want is an Observer design pattern.

    0 讨论(0)
提交回复
热议问题