overexchange
overexchange

Reputation: 1

How class is constructed?

For the below code in python 3,

class Spam(object):
  def __init__(self,name):
    self.name = name
  def bar(self):
    print('Am Spam.bar')

metaclass for Spam is type and base class for Spam is object.


My understanding is,

the purpose of base class is to inherit the properties. Metaclass is to construct the given class definition, as shown below,

body= \
"""
def __init__(self, name):
  self.name = name
def bar(self):
  print('Am ', self.name)
"""
clsdict = type.__prepare__('type', 'Spam', (object,))
exec(body, globals(), clsdict)
Spam = type('Spam', (object,), clsdict)


s = Spam('xyz')
s.bar()

Code is tested here.


With the given syntax def __prepare__(metacls, name, bases) to use,

Does __prepare__() require passing 'type' as first argument?

Upvotes: 0

Views: 72

Answers (1)

Dunes
Dunes

Reputation: 40703

type.__prepare__ is a bit special, in that it ignores all and any arguments passed to it and returns an empty dict.

>>> type.__prepare__()
{}

That said, you are not calling __prepare__ correctly. It is called with: the name of the class to be created, its bases and any keyword arguments the class is being created with. __prepare__ is called as metaclass.__prepare__(name, bases, **kwds) Thus,

class MyClass(SomeBase, arg="value", metaclass=MyMeta):
    ...

will have __prepare__ called as:

MyMeta.__prepare__("MyClass", (SomeBase,), arg="value")

However, most user defined meta classes define their __prepare__ as a classmethod meaning the metaclass is implicitly passed. Meaning your __prepare__ definition can look like:

@classmethod
def __prepare__(metaclass, name, bases, **kwargs):
    ...

But __prepare__ is still called in the same way as before. It is through the magic of descriptors that the metaclass argument is added.

Upvotes: 2

Related Questions