Home > Back-end >  Why is my object render function displaying None?
Why is my object render function displaying None?

Time:04-24

So I'm currently building a Html rendering program in Python which uses two base classes:

  1. SingleTag - Used for tags that don't have any children such as a

    tag

  2. ContainingTag - For tags that have nested tags such as the Html tag, Div tag etc...

Here is the file which contains those classes, along with the subclasses that inherit from them:

class ContainingTag:
    def __init__(self, children):
        self.open_tag = "<"   self.__class__.__name__.lower()   ">"
        self.close_tag = "</" self.__class__.__name__.lower()   ">"
        self.children = children

    def render(self):
        print("\t"   self.open_tag)
        for child in self.children:
            print("\t \t"   str(child.render()))
        print("\t"   self.close_tag)
class SingleTag:
    """A class to represent an html tag"""

    # Class initialiser
    def __init__(self, inner_html):
        self.open_tag = "<"   self.__class__.__name__.lower()   ">"
        self.close_tag = "</" self.__class__.__name__.lower()   ">"
        self.inner_html = inner_html

    # Prints html
    def render(self):
        return self.open_tag   self.inner_html   self.close_tag
class Html(ContainingTag):
    def __init__(self, children):
        super().__init__(children) 
        self.open_tag = "<!DOCTYPE html>\n"  "<"   self.__class__.__name__.lower()   ">"
    
    def render(self):
        print(self.open_tag)

        for child in self.children:
            print("\t \t"   str(child.render()))
        print(self.close_tag)


class Head(ContainingTag):
    def __init__(self, children):
        super().__init__(children)

class Style(ContainingTag):
    def __init__(self, children):
        super().__init__(children)

class Body(ContainingTag):
    def __init__(self, children):
        super().__init__(children)  

class Div(ContainingTag):
    def __init__(self, children):
        super().__init__(children)

class P(SingleTag):
    def __init__(self, inner_html=None):
        super().__init__(inner_html=None)
        self.inner_html = inner_html

When using the render method on a SingleTag object, it renders as expected, but when using the render method on a ContainingTag, it prints 'None' after every closing tag like this:

<Opening ContainingTag>
<Closing ContainingTag>
None

Can someone explain why this keeps printing and how to fix this? Thanks.

CodePudding user response:

The error seems to be that the render function does not actually return anything so the default i.e None is returned.

def render(self):
        print(self.open_tag)

        for child in self.children:
            print("\t \t"   str(child.render()))
        print(self.close_tag)
        # Add a return statement

CodePudding user response:

A simpler approach:

  • Override the built-in __str__() method instead of creating render
  • Pass the tag name as a parameter to the class contructor, so you don't need to create a lot of subclasses (you may still want to create a HTML subclass)
class ContainingTag:
    def __init__(self, name, children):
        self.name = name
        self.children = children

    def __str__(self):
        return f'<{self.name}>\n'   ''.join([str(c) for c in self.children])   f'</{self.name}>\n'
        
class SimpleTag:
    def __init__(self, name, html):
        self.name = name
        self.html = html

    def __str__(self):
        return f'<{self.name}>{self.html}</{self.name}>\n'

p1=SimpleTag('P', 'Hello')
p2=SimpleTag('P', 'World')
d=ContainingTag('DIV', [p1,p2])
b=ContainingTag('BODY', [d])

print(str(p1))
<P>Hello</P>

print(str(b))
<BODY>
<DIV>
<P>Hello</P>
<P>World</P>
</DIV>
</BODY>
  • Related