Oddthinking
Oddthinking

Reputation: 25282

TypeError: object() takes no parameters - but only in Python 3

I'm migrating some code from Python 2 to Python 3, and I am getting different behaviour. Looking through the lists of "what's changed" hasn't pointed me to any relevant differences, but presumably I've missed a big one.

I have simplified my code as much as possible to get this 'minimal faulty program':

def decorator(Type):
    """ This is a class decorator. It replaces a class with a subclass which
    *should be* equivalent.

    The result works on Python 2.7 but not on Python 3.4. """

    class FactorySubclass(Type):
        """ This subclasses from the provided type, and overrides the __new__
            and __init__ methods, but replaces them with exact equivalents,
            so I can't see how this has any effect. """

        def __new__(cls, *args, **kwargs):
            # Simplified this code to do basically nothing.
            # If this line is removed, it works on both versions.
            return Type.__new__(cls, *args, **kwargs)

        def __init__(self, *args, **kwargs):
            # Simplified this code to do basically nothing.
            Type.__init__(self, *args, **kwargs)

    return FactorySubclass


@decorator
class ExampleClass(object):
    def __init__(self, param=3):
        print("Constructed example instance")


ec = ExampleClass(param=5)

This code runs, and prints Constructed example instance in Python 2.7. This code fails, and dumps a stack trace in Python 3.4.

Traceback (most recent call last):
  File "mfp.py", line 31, in <module>
    ec = ExampleClass(param=5)
  File "mfp.py", line 16, in __new__
    return Type.__new__(cls, *args, **kwargs)
TypeError: object() takes no parameters

Typically this error means that someone has misspelled __init__ (and so constructor parameters are bypassing the relevant class and being given to object's parameterless constructor, but that doesn't seem to be the case here.

Oh, and as an afterthought, I confirmed that, yes, the value of param was 5 in Python 2.7.

2to3 gives it a clean-bill of health.

Please give me a pointer to a change in Python 3 that would invalidate this code, so I may read more about it.

Upvotes: 7

Views: 6909

Answers (1)

Ethan Furman
Ethan Furman

Reputation: 69031

You have the answer in your question:

Typically this error means [...] constructor parameters are [...] being given to object's parameterless constructor [...]

To fix, change your decorator to only add __init__ and __new__ if the passed-in Type has those methods.

Upvotes: 2

Related Questions