3

So I am making a basic directory system in python from scratch. I am pretty new to coding and am doing python as a Uni module. So I have made the functions for creating the tree from scratch, but now I have been tasked with actually just printing out the object as it is (not visually to see each step of the directory tree). So this is my code currently

class File:
    pass

class Directory(File):
    def __init__(self, name, left=None, right=None):
        self.name = name
        self.left = left
        self.right = right
        
    
    def __repr__(self):
        return f"{self.name}, {self.left}, {self.right}"
        

class PlainFile(File):
    def __init__(self, name):
        self.name = name
    
    def __str__(self):
        return self.name

When I try to print root, I want to essentially see the whole thing. But it gives me the <main.blahblah when printing the names of the classes and other parts too. I think my def__repr__ needs to be recursive in nature but for the life of me I have no clue how to do it:( Please help!

BanAckerman
  • 103
  • 1
  • 8
  • Unrelated to your direct question, but it seems like none of your directories have a `right` node since you've assigned a list to the `left`. Not sure if that's intended, but it seems a bit strange. – rchome Nov 29 '21 at 06:12
  • They do have right nodes unless they are a PlainFile (which is a leaf node). However Issac directory only has one node. Please see updated question for image of tree. – BanAckerman Nov 29 '21 at 14:20
  • If you print `root.right`, you will get `None`. This is because the directory called `"home"` is the second entry in the list stored in `root.left`. – rchome Nov 29 '21 at 15:01
  • Ah okay, how would I change this? – BanAckerman Nov 29 '21 at 15:58
  • Get rid of the brackets `[]` that make it a list. – rchome Nov 29 '21 at 16:17
  • 1
    I thought of something else that has simplified it all massively. Instead of using self.right and self.left I have just defined self.List_of_contents. What do you think of this? – BanAckerman Nov 29 '21 at 17:18
  • that seems reasonable – rchome Nov 29 '21 at 18:27
  • I did it and it worked perfectly! Thank you for all the help it means a lot! Now I want to print it out so that it shows the directory system with each directory and it's sub directories using indentation to show it's depth in the system. How would I go about this? – BanAckerman Nov 29 '21 at 19:14
  • That probably belongs in a different question from this one. – rchome Nov 29 '21 at 19:25
  • You're right. Thanks again :) – BanAckerman Nov 29 '21 at 19:27

1 Answers1

1

If you make your PlainFile class implement __repr__(self) instead of __str__(self), it should work. See What is the difference between __str__ and __repr__? for more details. The good thing about your Directory class's __repr__ is that it's already recursive, since it would call the inner File's __repr__ functions when evaluating the f-string.

Edit: Adding a full solution to match the expected output.

class File:
    pass

class Directory(File):
    def __init__(self, name, left=None, right=None):
        self.name = name
        self.left = left
        self.right = right

    def __repr__(self):
        arg_str = ", ".join(
            str(arg)
            for arg in (self.name, self.left, self.right)
            if arg is not None
        )
        return f"Directory({arg_str})"


class PlainFile(File):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f"PlainFile({self.name})"

I use str() in the Directory implementation because it doesn't add quotes to the self.name since it's a string. By default, __str__ is implemented as __repr__, so it would also work on the File objects in left or right, and calling str() on a list will make it call repr() on its items.

rchome
  • 2,623
  • 8
  • 21
  • Thank you very much, okay so I did that and now it prints most of everything. However It prints 'none' where there is not a branch. To get rid of this none and make it exactly like the picture I linked, would I just include an if statement somewhere saying if = none print "" ? Also, the other thing I want is for it to also print where the class names have been called. In the picture I linked, it includes the whole object as originally written, including where it says Directory or PlainFile for example. How would I achieve this? – BanAckerman Nov 29 '21 at 03:30
  • 1
    Yep you would need some if statements checking if the `left` or `right` are `None` when constructing your string. You can get the name of the class using `type(self).__name__`, or you could just hardcode it. – rchome Nov 29 '21 at 05:46
  • 1
    @BanAckerman I updated the answer with a full solution. – rchome Nov 29 '21 at 06:08