9

I have a class sysprops in which I'd like to have a number of constants. However, I'd like to pull the values for those constants from the database, so I'd like some sort of hook any time one of these class constants are accessed (something like the getattribute method for instance variables).

class sysprops(object):
    SOME_CONSTANT = 'SOME_VALUE'

sysprops.SOME_CONSTANT  # this statement would not return 'SOME_VALUE' but instead a dynamic value pulled from the database.
0

3 Answers 3

3

Although I think it is a very bad idea to do this, it is possible:

class GetAttributeMetaClass(type):
    def __getattribute__(self, key):
        print 'Getting attribute', key

class sysprops(object):
    __metaclass__ = GetAttributeMetaClass
Sign up to request clarification or add additional context in comments.

2 Comments

I think this is the perfect answer. Why do you think it's very bad idea? Is it because of the taboo around the metaclass
@ShipluMokaddim In general it's better to define properties explicit than implicit. Where a metaclass already allows for some "magic" by dynamically adding methods/properties to classes, making the metaclass itself magic makes it even harder to trace how/why code works.
2

While the other two answers have a valid method. I like to take the route of 'least-magic'.

You can do something similar to the metaclass approach without actually using them. Simply by using a decorator.

def instancer(cls):
    return cls()

@instancer
class SysProps(object):
    def __getattribute__(self, key):
        return key # dummy

This will create an instance of SysProps and then assign it back to the SysProps name. Effectively shadowing the actual class definition and allowing a constant instance.

Since decorators are more common in Python I find this way easier to grasp for other people that have to read your code.

2 Comments

It should be noted that this makes it impossible to instantiate the SysProps class. Instead of using this method I would actually opt for simply doing SysProps = SysProps() instead, seems clearer to me :)
You may not always want a user to instantiate a class--Singleton pattern.
0

sysprops.SOME_CONSTANT can be the return value of a function if SOME_CONSTANT were a property defined on type(sysprops).

In other words, what you are talking about is commonly done if sysprops were an instance instead of a class.

But here is the kicker -- classes are instances of metaclasses. So everything you know about controlling the behavior of instances through the use of classes applies equally well to controlling the behavior of classes through the use of metaclasses.

Usually the metaclass is type, but you are free to define other metaclasses by subclassing type. If you place a property SOME_CONSTANT in the metaclass, then the instance of that metaclass, e.g. sysprops will have the desired behavior when Python evaluates sysprops.SOME_CONSTANT.


class MetaSysProps(type):
    @property
    def SOME_CONSTANT(cls):
        return 'SOME_VALUE'

class SysProps(object):
    __metaclass__ = MetaSysProps


print(SysProps.SOME_CONSTANT)

yields

SOME_VALUE

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.