Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python metaclasses at module level

I read What is a metaclass in Python?

and I tried to replicate the upper metaclass from the example and found that this doesn't work in all cases:

def upper(cls_name, cls_parents, cls_attr):                                     
    """ Make all class attributes uppper case """                               
    attrs = ((name, value) for name, value in cls_attr.items()                  
            if not name.startswith('__'))                                       
    upper_atts = dict((name.upper(), value) for name, value in attrs)           
    return type(cls_name, cls_parents, upper_atts)                              

__metaclass__ = upper #Module level
class Foo:                                                                      
    bar = 1                                                                     
f =  Foo()
print(f.BAR) #works in python2.6

The above fails (with an attribute error) in python3 which I think is natural because all classes in python3 already have object as their parent and metaclass resolution goes into the object class.

The question:

How do I make a module level metaclass in python3?

like image 413
Alex Plugaru Avatar asked Aug 11 '11 09:08

Alex Plugaru


People also ask

What are the metaclasses in Python?

A metaclass is the class of a class. A class defines how an instance of the class (i.e. an object) behaves while a metaclass defines how a class behaves. A class is an instance of a metaclass.

Why would you use metaclasses Python?

A metaclass in Python is a class of a class that defines how a class behaves. A class is itself an instance of a metaclass. A class in Python defines how the instance of the class will behave. In order to understand metaclasses well, one needs to have prior experience working with Python classes.

Are metaclasses inherited?

Defining Metaclasses Principially, metaclasses are defined like any other Python class, but they are classes that inherit from "type". Another difference is, that a metaclass is called automatically, when the class statement using a metaclass ends.

How do you set the metaclass of class A to B?

In order to set metaclass of a class, we use the __metaclass__ attribute. Metaclasses are used at the time the class is defined, so setting it explicitly after the class definition has no effect.


1 Answers

The module level metaclass isn't really "module level", it has to do with how class initialization worked. The class creation would look for the variable "__metaclass__" when creating the class, and if it wasn't in the local environment it would look in the global. Hence, if you had a "module level" __metaclass__ that would be used for every class afterwards, unless they had explicit metaclasses.

In Python 3, you instead specify the metaclass with a metaclass= in the class definition. Hence there is no module level metaclasses.

So what do you do? Easy: You specify it explicitly for each class.

It's really not much extra work, and you can even do it with a nice regexp search and replace if you really have hundreds of classes and don't want to do it manually.

like image 120
Lennart Regebro Avatar answered Sep 28 '22 10:09

Lennart Regebro