Python static setters and getters?

Question:

I have put a Jira client for my django application together and now need to make it static but I can’t figure how to convert @property and @?.setter into static fields:

Say I have a class:

class nothing(object):
    auth_token = None
    counter = 0

    @property
    def a(self):
        self.log('getter')
        if not self.auth_token:
            self.auth_token = 'default'
        return self.auth_token

    @a.setter
    def a(self, value):
        self.log('setter')
        self.auth_token = value

    def log(self, value):
        self.counter+=1
        print '{0} called / counter: {1}'.format(value, self.counter)

and I want its methods to be static:

class nothing:
    auth_token = None
    counter = 0

    @staticmethod
    def get_a():
        nothing.log('getter')
        if not nothing.auth_token:
            nothing.log('auth_token value is None, setting')
            nothing.auth_token = 'default'
        return nothing.auth_token

    @staticmethod
    def set_a(value):
        nothing.log('setter')
        nothing.auth_token = value

    @staticmethod
    def log(value):
        nothing.counter+=1
        print '{0} called / counter: {1}'.format(value, nothing.counter)

can’t mark get_a as @property now as calling it will return an object and not actually call get_a. Methods are something I can live with but is there a way to have getters/setters instead?

Asked By: abolotnov

||

Answers:

The easiest way is to make this class singleton. Instead of making methods static, override class with its instance:

nothing = nothing()

You can also use metaclasses if you want to have more than one instance.

http://en.wikibooks.org/wiki/Python_Programming/MetaClasses

Answered By: Michał Zieliński

You need a class property in python?

here is a solution for the getter. For the setter an other metaclass than type is required.

>>> class CP(object):
    def __init__(self, getter, setter = None):
        self._getter = getter
        self._setter = setter

    def setter(self, setter):
        self._setter = setter
    def __get__(self, obj, cls = None):
        print '__get__', obj, cls
        return self._getter(cls) # for static remove cls from the call
    def __set__(self, *args):
        print args


>>> class X(object):
    @CP
    def g(cls):
        print 'g', cls
        return 1


>>> X.g # getting returns value of g
__get__ None <class '__main__.X'>
g <class '__main__.X'>
1
>>> X().g
__get__ <__main__.X object at 0x02ACEC50> <class '__main__.X'>
g <class '__main__.X'>
1
>>> X.g = 3 # setting does not work
>>> X.g
3

But when I have a look at:

>>> X().g = 3
(<__main__.X object at 0x02ACEE50>, 3)

It seems not intended for properties to __set__ on class side. This is wise because: how else would you even be able to overwrite for example a property on class side if __set__ was called?

Answered By: User

The following is an example of using metaclasses. This example implements a naming convention where class ISomeClass is what we have dubbed an ‘abstract interface’, and class Igloo and class Panda are not:

class MyObjectsInterfaceNamingMetaclass(type):
    @property
    def isAbstract(cls):
        '''requires class name >1 chars'''
        return cls.__name__.startswith('I') and cls.__name__[1].isupper()

in use:

class IBlueprinted(metaclass=MyObjectsInterfaceNamingMetaclass):
    pass

class FabricBlueprint(IBlueprinted):
    pass

class IToyBlueprint(IBlueprinted):
    pass
class RedToyBlueprint(IToyBlueprint):
    pass

demo:

print(IBlueprinted.isAbstract)     #True

print(FabricBlueprint.isAbstract)  #False

print(IToyBlueprint.isAbstract)    #True
print(RedToyBlueprint.isAbstract)  #False
Answered By: ninjagecko
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.