Reputation: 23
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
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?
class MetaOne(metaclass=ABCMeta):
pass
class Eggs(MetaOne):
pass
class Spam(Eggs):
pass
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
.
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
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
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