简体   繁体   中英

Python: Printing nested classes

What's the best way to print the contents of a nested class? For example:

class Library():
    def __init__(self):
        self.shelves = []
        self.shelf = self.Shelf()

    class Shelf():
        def __init__(self):
            self.books = []


x = Library()

I know vars(x) works if the class is not nested. But if it is, I get something like:

{'shelf': <__main__.Shelf instance at 0x7f4bae723560>, 'shelves': []}

as the output. How do I get python to print it out as:

{'shelf': {'books': []}, 'shelves': []}

You are aiming to have a string version of your objects. Python knows two methods for this: __repr__() and __str__() . The first is meant to be a string which, if interpreted as Python source, would re-generate the thing it represents. If you just call vars(x) you receive a dict of all fields in the given x . Most means to output this dict (and probably also yours) make it call the __repr__() function of each of its contents. That's why you see that ugly string <__main__.Shelf instance at 0x7f4bae723560> because that's the __repr__() of your Shelf object.

I propose to implement it and thus override the standard implementation. You will have to do that in Shelf :

class Library():
    def __init__(self):
        self.shelves = []
        self.shelf = self.Shelf()

    class Shelf():
        def __init__(self):
            self.books = []
        def __repr__(self):
            return repr(vars(self))

x = Library()

And while you're at it, you could do the same in your Library as well; then typing x alone (ie instead of vars(x) ) would also give the nice output:

class Library():
    def __init__(self):
        self.shelves = []
        self.shelf = self.Shelf()
    def __repr__(self):
        return repr(vars(self))

    class Shelf():
        def __init__(self):
            self.books = []
        def __repr__(self):
            return repr(vars(self))

x = Library()

And of course you can refactor that out and put that aspect into a base class:

class Representer(object):
    def __repr__(self):
        return repr(vars(self))

class Library(Representer):
    def __init__(self):
        self.shelves = []
        self.shelf = self.Shelf()

    class Shelf(Representer):
        def __init__(self):
            self.books = []

x = Library()

First, I would recommend that you not nest classes. There isn't really any reason to do so.

Second, you're seeing exactly what you're supposed to: the value for the shelf variable is a Shelf object, and you haven't defined any special appearance (or "reproduction") for it. Since vars is not recursive, you see the default appearance with a memory location.

If you want to see the contents of a vars() call on a Shelf object when printing the Shelf object, you can define a __repr__ method for Shelf that calls vars() on itself:

class Library():
    def __init__(self):
        self.shelves = []
        self.shelf = self.Shelf()
    class Shelf():
        def __init__(self):
            self.books = []
        def __repr__(self):
            return str(vars(self))

>>> x = Library()
>>> vars(x)
{'shelf': {'books': []}, 'shelves': []}

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