简体   繁体   中英

A Python Inheritance Problem: TypeError: super() argument 1 must be type, not None

I want to save the class name and class itself into a python dict by using a decorator.

from functools import wraps
models = {} # python dict which save class name and class

def register_model(name):
    def register(func):
        @wraps(func)
        def inner(name):
            models[name] = func

        return inner(name)

    return register

# `A` is a class that I want to save into the dict.

@register_model('1244')
class A(object):
    a = 1

    def __init__(self):
        super(A, self).__init__()

# But when call it below:

print(models['1244']().a)

I get an error:

Traceback (most recent call last):
  File "/Data/Usr/t.py", line 50, in <module>
    print(models['1244']().a)
  File "/Data/Usr/t.py", line 36, in __init__
    super(A, self).__init__()
TypeError: super() argument 1 must be type, not None

I solve this error by changing super(A, self).__init__() to super().__init__()

I want to know why augment 1 is None and what cause it.

The decorator doesn't return anything, and whatever it returns will be assigned to the name A (the class definition). You're making the class accessible solely through models['1244'] , A() as such doesn't work (because A is None ). This is what's happening when you do super(A, ...) .

  1. You don't need to pass A to super , just super().__init__() will do just fine. This would resolve this particular problem.
  2. Your decorator should return the class.

In fact, your decorator is overly complicated. inner is completely superfluous. Change it to this to solve both issues:

def register_model(name):
    def register(cls):
        models[name] = cls
        return cls

    return register

Now it just registers the class in models and otherwise lets it pass through unchanged.

Your decorator returns None , so A in the original scope ends up being None , and super(A, self) with A = None is an invalid call. The simple fix is to return func from the decorator.

Simplifying your code and getting rid of outdated idioms such as inheriting from object and super(..., ...) , things work fine:

models = {}


def register_model(name):
    def register(cls):
        models[name] = cls
        return cls

    return register


@register_model('1244')
class A:
    a = 1

    def __init__(self):
        super().__init__()
        print("Hi!")


print(models['1244']().a)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM