What is the best way for a class to reference itself in a class attribute?

Use a meta class to automatically set it.

def my_meta(name, bases, attrs):
    cls = type(name, bases, attrs)
    cls.bar = cls
    return cls


class Foo(object):
    __metaclass__ = my_meta


>>> print Foo.bar
<class '__main__.Foo'>

You can use a class decorator

def moi(fieldname):
    def _selfref(cls):
        setattr(cls, fieldname, cls.__name__)
        return cls

    return _selfref

usage:

@moi('bar')
class Foo(object):
    pass

then:

>>> print Foo.bar
Foo

You could define a class decorator that replaced placeholder strings with the class being defined:

def fixup(cls):
    placeholder = '@' + cls.__name__
    for k,v in vars(cls).items():
        if v == placeholder:
            setattr(cls, k, cls)
    return cls

@fixup
class Foo(object):
    bar = '@Foo'

print('Foo.bar: {!r}'.format(Foo.bar))  # -> Foo.bar: <class '__main__.Foo'>

Another alternative would be to use the __init_subclass__() special method which was introduced in Python 3.6 to create a base class and then derive your class from it instead of the generic object:

class Base(object):
    def __init_subclass__(cls, /, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.bar = cls

class Foo(Base):
    pass

print('Foo.bar: {!r}'.format(Foo.bar))  # -> Foo.bar: <class '__main__.Foo'>

You can use metaclasses. Define a __new__ which iterates over set attributes and then sets the back pointer to the class itself.

Tags:

Python