1

I am trying to learn about metaclasses in python 3.7 and have the following code

class Foo(type):

    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        return super().__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):
        return super().__call__(cls, *args, **kwargs)


class Bar(metaclass=Foo):

    def __new__(cls, *args, **kwargs):
        print(cls)
        print(args)
        print(kwargs)
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        return super().__init__(*args, **kwargs)


b = Bar()

When I run it I get the output

<class '__main__.Bar'>
(<class '__main__.Bar'>,)
{}

and the error

File "meta/main.py", line 91, in __new__
    return super().__new__(cls, *args, **kwargs)
TypeError: object.__new__() takes no arguments

where the line correpondse to the __new__ call in Bar

I can't work out why the second <class '__main__.Bar'> is being passed in. If I change Bar to not use the Foo metaclass (i.e. change class Bar(metaclass=Foo): to class Bar:) I get

<class '__main__.Bar'> 
()
{}

and no errors (as I would expect). Thanks for any help

1 Answer 1

2

You are passing in an extra argument on calls:

def __call__(cls, *args, **kwargs):
    return super().__call__(cls, *args, **kwargs)

__call__ is not an implicit static method, drop that cls argument:

def __call__(cls, *args, **kwargs):
    return super().__call__(*args, **kwargs)
Sign up to request clarification or add additional context in comments.

Comments

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.