15

I want to merge constraints from the current and inherited classes only once a class is loaded (not per object!).

class Domain(Validatable):
 constraints = {...}

To do this I defined a method _initialize_class_not_instance that should be called once for each class:

class Validatable:
 @classmethod
 def _initialize_class_not_instance(cls):
 # merge constraints from derived class and base classes
 pass
 __class__._initialize_class_not_instance() # doesn't work
 # Validatable._merge_constraints() # doesn't work too

The problem is that __class__ doesn't exist in this context and Validatable is not defined too. But I want to avoid, that the user of my API has to call the initialize method explicitely or has to use an additional class decorator.

Any ideas how to initialize the class?

asked May 31, 2011 at 6:20
1
  • Note that classes are instances, usually they are instances of type but as @Ignacio has pointed out they can be instances of a custom subclass of type. Commented May 31, 2011 at 8:01

2 Answers 2

17

Use a metaclass.

class MetaClass(type):
 def __init__(cls, name, bases, d):
 type.__init__(cls, name, bases, d)
 cls.foo = 42
class MyClass(object):
 __metaclass__ = MetaClass
print MyClass.foo
answered May 31, 2011 at 6:23
Sign up to request clarification or add additional context in comments.

3 Comments

for the record, in python3, it's MyClass(object, metaclass=MetaClass)
Why do you need the MetaClass? Why not just put the statement "MyClass.foo = 42" after the definition of "MyClass"?
The point is to encapsulate the initialisation logic inside the class @ErelSegal-Halevi. OP explicitly mentions he does not want to have the user do any of the work. It should all happen inside the class.
2

I ended up with a class decorator and without inheritance. This decorator merges the constraints of the current and inherited classes and overrides the __init__ method:

def validatable(cls):
 # merge constraints from derived class and base classes here ...
 original_init = cls.__init__
 def init_to_insert(self, *args, **keywords):
 self.errors = {}
 original_init(self, *args, **keywords) 
 cls.__init__ = init_to_insert
 return cls

This is the key for my solution, since the decorator has to modify the class (merging constraints and inserting methods) and instances.

answered May 31, 2011 at 17:12

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.