0

If I had multiple classes inside another class, how would I get a list of the names of the child classes?

class commands:
    class hello:
        desc = "says hello"
    class exec:
        desc = "executes code"

My wish is to get a list of the commands similar to ["hello", "exec"]. So far I've only found information about subclasses and recursive classes but nothing about actually finding the names of these.

  • 2
    Why do you have this structure in the first place? – roganjosh Apr 09 '21 at 23:07
  • Context is similar to a help page. Example: `print(commands.hello.desc)` . I'm trying to work with getting a list of functions and extra information about them, but these are currently separated into classes and functions. – Floris_Fireball Apr 09 '21 at 23:10
  • 1
    `commands.__dict__`, `vars(commands)`, or `dir(commands)` would output all members of the class, but that also includes methods and other variables. – ArjunSahlot Apr 09 '21 at 23:12
  • 2
    Those aren't child classes. You'd have to introspect the class namespace, but there is no guarantee that the class objects were *defined* within the class body. Note, nested classes like this aren't a common pattern in Python, they serve little purpose. – juanpa.arrivillaga Apr 09 '21 at 23:13
  • What would you suggest I should do for something like this? I tried using dictionaries for the same method, but then you use dict["item"] instead of dict.item, and the latter looks neater. – Floris_Fireball Apr 09 '21 at 23:16
  • 1
    @Floris_Fireball, If dicts were like that in python, it wouldn't work because, if you were to have a item named "clear", then running it would cause collision due to dicts already having a clear method `dict.clear` – ArjunSahlot Apr 09 '21 at 23:21
  • Oh, ok, I don't think the OP does either. This is definitely an XY problem. Fighting the syntax of Python to get it to something like, say, JavaScript, is just a losing battle. You'll get your "neater" syntax and the rest of the structure goes down the toilet – roganjosh Apr 09 '21 at 23:32
  • 1
    What *problem do you expect to solve* by putting `hello` and `desc` inside a `commands` class, rather than at the top level of the file? What, conceptually, is "a commands"? Does it make sense for me to write code somewhere else like `x = commands()`? If not, it *should not be a class*. Classes aren't just there to make namespaces. The *module* already provides a namespace for you, anyway. – Karl Knechtel Apr 10 '21 at 02:21

1 Answers1

1

Any of these should work generally:

print([k for k, v in commands.__dict__.items() if isinstance(v, type)])
import inspect

print([k for k, v in commands.__dict__.items() if inspect.isclass(v)])
print([k for k, v in vars(commands).items() if isinstance(v, type)])
import inspect

print([k for k, v in vars(commands).items() if inspect.isclass(v)])

There are also more options in these SO threads:

  1. python - how to get a list of inner classes?.
  2. List all inner classes of a given class - Python

All 4 commands output:

['hello', 'exec']

Tested on the following structure to ensure that nothing other than class instances would appear in the output:

class Other:
    pass


class commands:
    a = 2
    o = Other()

    class hello:
        desc = "says hello"

        def rand(self):
            pass

    class exec:
        desc = "executes code"

        def rand(self):
            pass

    def clear(self):
        pass
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57