Stefano Sarioli
Stefano Sarioli

Reputation: 23

How to apply a metaclass to all my class without hardcoding it in the class declaration

for an exam the professor ask me to write a metaclass that take effect on all the class in the project without declaring it directly in the class declaration, is that possible? how? For example i have the following code:

class MetaOne(type): 
    def __new__(meta, classname, supers, classdict):
        print('In MetaOne.new: ', classname, supers, classdict, sep='\n...') 
        return type.__new__(meta, classname, supers, classdict) 
    def __init__(Class, classname, supers, classdict): 
        print('In MetaOne init:', classname, supers, classdict, sep='\n...') 
        print('...init class object:', list(Class.__dict__.keys()))

class Eggs: pass 

print('making class') 

class Spam(Eggs): 
    data = 1 
    def meth(self, arg): pass 

print('making instance') 
X = Spam() 
print('data:', X.data)

And i want that the output is equal to the output of the following code:

class MetaOne(type): 
    def __new__(meta, classname, supers, classdict):
        print('In MetaOne.new: ', classname, supers, classdict, sep='\n...') 
        return type.__new__(meta, classname, supers, classdict) 
    def __init__(Class, classname, supers, classdict): 
        print('In MetaOne init:', classname, supers, classdict, sep='\n...') 
        print('...init class object:', list(Class.__dict__.keys()))

class Eggs: pass 

print('making class') 

class Spam(Eggs, metaclass=MetaOne): 
    data = 1 
    def meth(self, arg): pass 

print('making instance') 
X = Spam() 
print('data:', X.data)

The metaclass as to be applied to all my class even if i don't declare it directly. I had red a lot of question about metaclasses, but at the end all use always the metaclass=meta declaration in he definition of their class.

Upvotes: 2

Views: 80

Answers (2)

Douglas Denhartog
Douglas Denhartog

Reputation: 2054

Well, it is very difficult for me to understand your question.

If Eggs inherits MetaOne and Spam inherits Eggs, does this accomplish what you are trying to do?

Example #1:

class MetaOne(metaclass=ABCMeta):
    pass

class Eggs(MetaOne):
    pass

class Spam(Eggs):
    pass

Example #2:

Perhaps the information available at lgiordani.com will be of use to you, especially the following code block from the preceding link:

class FilterClass(type):
    @classmethod
    def __prepare__(name, bases, **kwds):
        return collections.OrderedDict()

    def __new__(metacls, name, bases, namespace, **kwds):
        result = type.__new__(metacls, name, bases, dict(namespace))
        result._filters = [
            value for value in namespace.values() if hasattr(value, '_filter')]
        return result

This block of code demonstrates how to create a metaclass without using metaclass=ABCMeta.

Example #3:

Are you familiar with super()?

class MetaOne:
    def __init__(self, name):
        self.name = name

class Eggs: pass

class Spam(MetaOne, Eggs):
    def __init__(self, name, is_tasty):
        super().__init__(name)
        self.is_tasty = is_tasty

>>> s = Spam('meta', True)
>>> s
<__main__.Spam object at 0x100705b38>
>>> s.name
'meta'
>>> s.is_tasty
True

Though using super() isn't really metaclass

Example #4:

Depending on your version of Python, you may be able to define __metaclass__ = MetaOne at the module level, which would affect ALL classes below that declaration.

class MetaOne: pass

class Eggs: pass

__metaclass__ = MetaOne

class Spam: pass
class Scrambled: pass
class Fried: pass

In this use case, the metaclass of Spam, Scrambled and Fried would all be MetaOne.

Upvotes: 0

Walle Cyril
Walle Cyril

Reputation: 3247

You can write __metaclass__ = your_metaclass at a module level. All classes defined below will use that metaclass. You can overwrite this if you write __metaclass__ = type again in the class definiton. Child class are using the metaclass of the parent.

Upvotes: 2

Related Questions