2

I am new to python metaclass and running the following code:

    class A(type):

        @classmethod
        def _handle_attrs(cls, class_name, bases, attrs, **kwargs):

            # Now lets find all handlers defined for this class
            current_attr = [(att, getattr(attrs[att], "__my_attr")) for att in attrs if
                          hasattr(attrs[att], '__my_attr')]

            print hasattr(attrs, '__my_attr') # returns False

        def __new__(cls, class_name, bases, attrs, **kwargs):
            cls._handle_attrs(class_name, bases, attrs, **kwargs)
            return type.__new__(cls, class_name, bases, attrs, **kwargs)


    # adding the decorators args as a class attribute

    def my_decorator(*args, **kwargs):
        def _my_decorator(cls):
            if hasattr(cls, '__my_attr'):
                cls.__my_attr.update(kwargs)
            else:
                cls.__my_attr = kwargs
            return cls
        return _my_decorator

    class B:
        __metaclass__ = A

        def get_attr_dict(self):
            return getattr(self, '__my_attr', None)


    @my_decorator(w = 'W')
    @my_decorator(z = 'Z')
    class C(B):
        x = 'X'
        y = 'Y'

    test = C()

    print test.__class__.__dict__ 
    print test.__my_attr # this returns {'w': 'W', 'z': 'Z'}

I am adding class attributes to C class by using the class decorator - my_decorator. In _handle_attrs function I would like to do something to the added attributes.

The problem is that the added attributes are added under : test._ _class__._ _dict__ and when creating C in metaclass, I don't know how to access them...

2
  • Python is a fantastic language to run and explore, and metaclasses provide a lot of possibilities - but you really should be doing that in Python 3 these days. Python 2.7 is almost ten years old, and missing lots and lots of new features. Commented Dec 29, 2017 at 12:06
  • Another thing: refrain from using a double underscore as prefix for your private attribute there: it will only run you into problem in your experiments. Python has no private attributes -the double-underscore triggers a compile time name mangling that will make your code error prone and very hard to debug. The convention is that a single underscore is the prefix to be used for private attributes. Commented Dec 29, 2017 at 12:10

1 Answer 1

2

The metaclass' __new__ is run upon the definition of a class that uses it. Since

@my_decorator(w = 'W', z = 'Z')
class C(B):
    x = 'X'
    y = 'Y'

is equivalent to

class C(B):
    x = 'X'
    y = 'Y'

C = my_decorator(w = 'W', z = 'Z')(C)

it should be evident that the metaclass has already done its job by the time your decorator adds its attributes.

Sign up to request clarification or add additional context in comments.

2 Comments

So is there a way to add the attributes from the decorator before the metaclass is running?
Not with a class decorator.

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.