How to Fix super() TypeError: 'argument 1 must be type, not classobj' in Python (Parent Class Not Inheriting from object)

If you’ve encountered the error TypeError: argument 1 must be type, not classobj while using super() in Python, you’re likely dealing with a conflict between old-style (classic) classes and new-style classes. This error arises because super(), a function used to call methods from a parent class, relies on features specific to new-style classes—features that old-style classes lack.

In this blog, we’ll demystify this error by explaining the difference between old-style and new-style classes, why super() fails with old-style classes, and provide step-by-step solutions to fix it. Whether you’re maintaining legacy Python 2 code or accidentally writing old-style classes in Python 3, this guide will help you resolve the issue.

Table of Contents#

  1. Understanding the Error
  2. Old-Style vs. New-Style Classes: What’s the Difference?
  3. Why Does super() Throw This Error with Old-Style Classes?
  4. How to Fix the Error
  5. Example Scenarios: Before and After Fixes
  6. Common Pitfalls to Avoid
  7. Conclusion
  8. References

1. Understanding the Error#

The error message TypeError: argument 1 must be type, not classobj occurs when super() is called with a class that is an old-style class (a classobj), rather than a new-style class (a type).

What’s a classobj?#

In Python 2, classes defined without explicitly inheriting from object are called "old-style classes" and have a type of classobj. New-style classes, which inherit from object (directly or indirectly), have a type of type.

super() expects the first argument to be a new-style class (i.e., an instance of type). When passed an old-style class (a classobj), it throws the error because classobj lacks the metadata (like __mro__ for method resolution order) that super() needs to function.

2. Old-Style vs. New-Style Classes: What’s the Difference?#

To resolve the error, it’s critical to understand the distinction between old-style and new-style classes.

Old-Style Classes (Python 2 Only)#

Old-style classes were the default in Python 2 if a class did not inherit from object. They lack several features of modern Python classes:

  • No support for super().
  • No consistent method resolution order (MRO).
  • No support for descriptors, properties, or advanced features like __slots__.

Example (Python 2):

# Old-style class (type is classobj)
class OldStyleParent:
    pass
 
print(type(OldStyleParent))  # Output: <type 'classobj'>

New-Style Classes (Python 3 Default)#

New-style classes inherit from object (directly or via another new-style class). They are the standard in Python 3, where all classes are new-style by default (even if you don’t explicitly inherit from object).

Key features:

  • Support for super().
  • A well-defined MRO (via __mro__ attribute).
  • Support for descriptors, properties, and advanced OOP features.

Example (Python 2 and 3):

# New-style class (type is type)
class NewStyleParent(object):  # Explicitly inherit from object (Python 2)
    pass
 
print(type(NewStyleParent))  # Output: <type 'type'> (Python 2) or <class 'type'> (Python 3)

Python 3 Note: In Python 3, class NewStyleParent: is equivalent to class NewStyleParent(object):—all classes implicitly inherit from object.

3. Why Does super() Throw This Error with Old-Style Classes?#

super() is designed to work with new-style classes by leveraging their MRO to find the next class in the inheritance hierarchy. Old-style classes:

  • Do not have an __mro__ attribute (MRO is undefined).
  • Do not support the super() function’s internal logic, which relies on the class being a type (not a classobj).

Example of Code That Triggers the Error#

Consider this Python 2 code, where Child inherits from an old-style Parent:

# Python 2 code (old-style Parent)
class Parent:  # Old-style: does not inherit from object
    def __init__(self):
        print("Parent __init__ called")
 
class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()  # Error here!
 
# Trigger the error
child = Child()

Output:

TypeError: super() argument 1 must be type, not classobj

Here, Parent is an old-style class (classobj), so super(Child, self) fails because Child’s parent is not a type.

4. How to Fix the Error#

The root cause is using an old-style parent class. The solution is to convert the parent class to a new-style class by ensuring it inherits from object.

Solution 1: Convert Parent Classes to New-Style Classes#

Update the parent class to inherit from object explicitly. This works in both Python 2 and 3.

Step-by-Step Fix:#

  1. Modify the parent class definition to inherit from object.
  2. Ensure all classes in the inheritance chain are new-style (if using multiple inheritance).

Fixed Example (Python 2):

# Parent is now a new-style class (inherits from object)
class Parent(object):  # Explicitly inherit from object
    def __init__(self):
        print("Parent __init__ called")
 
class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()  # Now works!
 
child = Child()  # Output: Parent __init__ called

Python 3 Note: In Python 3, you don’t need to explicitly inherit from object (all classes are new-style). However, if you’re writing code compatible with Python 2, adding (object) ensures new-style behavior.

If you cannot modify the parent class (e.g., it’s from a third-party library), you can call the parent method directly instead of using super(). However, this is a workaround and not recommended for maintainable code.

Example (Python 2):

class Parent:  # Old-style (unchangeable)
    def __init__(self):
        print("Parent __init__ called")
 
class Child(Parent):
    def __init__(self):
        Parent.__init__(self)  # Directly call parent method (no super())
 
child = Child()  # Output: Parent __init__ called (works, but not ideal)

Caveat: Direct calls bypass MRO and can lead to unexpected behavior in multiple inheritance.

5. Example Scenarios: Before and After Fixes#

Let’s walk through two common scenarios where this error occurs and how to fix them.

Scenario 1: Simple Inheritance (Python 2)#

Problem Code:

class Animal:  # Old-style parent (no object inheritance)
    def __init__(self, name):
        self.name = name
 
class Dog(Animal):
    def __init__(self, name, breed):
        super(Dog, self).__init__(name)  # Error! Animal is classobj
        self.breed = breed
 
dog = Dog("Buddy", "Golden Retriever")

Error:

TypeError: super() argument 1 must be type, not classobj

Fixed Code:

class Animal(object):  # New-style parent (inherits from object)
    def __init__(self, name):
        self.name = name
 
class Dog(Animal):
    def __init__(self, name, breed):
        super(Dog, self).__init__(name)  # Now works!
        self.breed = breed
 
dog = Dog("Buddy", "Golden Retriever")
print(dog.name)  # Output: Buddy

Scenario 2: Accidental Old-Style Class in Python 3#

Python 3 uses new-style classes by default, but if you’re porting Python 2 code and forget to remove (object) (or add it), could this error occur? No—Python 3 treats all classes as new-style, even without (object).

Python 3 Example (No Error):

class Animal:  # New-style in Python 3 (no need for object)
    def __init__(self, name):
        self.name = name
 
class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # super() works in Python 3!
        self.breed = breed
 
dog = Dog("Buddy", "Golden Retriever")
print(dog.name)  # Output: Buddy

Thus, the error is almost exclusively a Python 2 issue or a result of writing Python 2-style code in Python 3.

6. Common Pitfalls to Avoid#

To prevent this error, watch for these mistakes:

Pitfall 1: Forgetting object in Python 2#

Always inherit from object when defining classes in Python 2.

Pitfall 2: Mixing Old-Style and New-Style Classes#

If a child class inherits from a new-style class and an old-style class, the old-style parent will still cause issues. Ensure all parents are new-style.

Bad (Python 2):

class NewStyle(object): pass
class OldStyle: pass
 
class MixedChild(NewStyle, OldStyle):  # OldStyle is classobj
    def __init__(self):
        super(MixedChild, self).__init__()  # Error!

Good (Python 2):

class NewStyle(object): pass
class OldStyle(object): pass  # Convert OldStyle to new-style
 
class MixedChild(NewStyle, OldStyle):
    def __init__(self):
        super(MixedChild, self).__init__()  # Works!

Pitfall 3: Assuming Python 3 Compatibility#

If you’re writing code for Python 2 and 3, always inherit from object to ensure new-style behavior in Python 2. Python 3 will ignore the redundant (object) but still work.

7. Conclusion#

The TypeError: argument 1 must be type, not classobj is a relic of Python 2’s old-style classes. The fix is simple: convert the parent class to a new-style class by inheriting from object.

In Python 3, this error is rare because all classes are new-style by default. For Python 2 code, explicitly inheriting from object ensures super() works as expected, enabling proper inheritance and modern OOP features.

8. References#