Horrible abuse of __init_subclass__, or elegant hack?

Chris Angelico rosuav at gmail.com
Wed Mar 31 19:14:24 EDT 2021


I think this code makes some sort of argument in the debate about
whether Python has too much flexibility or if it's the best
metaprogramming toolset in the world. I'm not sure which side of the
debate it falls on, though.

class Building:
    resource = None
    @classmethod
    def __init_subclass__(bldg):
        super().__init_subclass__()
        print("Building:", bldg.__name__)
        def make_recipe(recip):
            print(recip.__name__.replace("_", " "), "is made in a",
bldg.__name__.replace("_", " "))
        bldg.__init_subclass__ = classmethod(make_recipe)


class Extractor(Building): ...
class Refinery(Building): ...

class Crude(Extractor):
    resource = "Oil"
    time: 1
    Crude: 1

class Plastic(Refinery):
    Crude: 3
    time: 6
    Residue: 1
    Plastic: 2

class Rubber(Refinery):
    Crude: 3
    time: 6
    Residue: 2
    Rubber: 2

Full code is here if you want context:
https://github.com/Rosuav/shed/blob/master/satisfactory-production.py

Subclassing Building defines a class that is a building. (The ellipsis
body is a placeholder; I haven't implemented stuff where the buildings
know about their power consumptions and such. Eventually they'll have
other attributes.) But subclassing a building defines a recipe that is
produced in that building. Markers placed before the "time" are
ingredients, those after the "time" are products.

There are actually a lot of interesting wrinkles to trying to replace
__init_subclass__ on the fly. Things get quite entertaining if you
don't use the decorator, or if you define and decorate the function
outside of the class, or various other combinations.

On a scale of 1 to "submit this to The Daily WTF immediately", how bad
is this code? :)

ChrisA


More information about the Python-list mailing list