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#
- Understanding the Error
- Old-Style vs. New-Style Classes: What’s the Difference?
- Why Does
super()Throw This Error with Old-Style Classes? - How to Fix the Error
- Example Scenarios: Before and After Fixes
- Common Pitfalls to Avoid
- Conclusion
- 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 atype(not aclassobj).
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:#
- Modify the parent class definition to inherit from
object. - 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__ calledPython 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.
Solution 2: Avoid super() with Old-Style Classes (Not Recommended)#
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: BuddyScenario 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: BuddyThus, 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.