Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Checking whether an object is a parameter in another object

I’m currently building a HTML renderer in Python and have this for the classes to handle the tags:

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 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)
        return ""
        

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)
        return ""

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):
        super().__init__(inner_html)
from tag import Html, P, Div, Head, Style, Body
 
html = Html([
        Div([
            Head([])
        ])    
    ])

print(html.render())
<!DOCTYPE html>
<html>
        <div>
        <head>
        </head>

        </div>

</html>

My single tags work fine printing inside a containing tag but when printing a containing tag inside another containing tag, the indention is on the same level, when I want it to be indented. Is there a way to check whether a containing tag is a child of another containing tag, so I can conditionally print the extra indentation?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The way I’ve always handled recursive indents like this is with a keyword argument to render (or whatever name the equivalent function has).

Also, you can save a lot of code by inheriting property functions, which act like attributes, instead of setting static values in the __init__ functions.

class Tag:

    @property
    def open_tag(self): return f'<{self.__class__.__name__.lower()}>'

    @property
    def close_tag(self): return f'</{self.__class__.__name__.lower()}>'

    def __str__(self):
        return self.render()

class SingleTag(Tag):

    def __init__(self, inner_html):
        self.inner_html = inner_html

    def render(self, indent=''):
        return f'{indent}{self.open_tag}{self.inner_html}{self.close_tag}\n'

class ContainingTag(Tag):

    def __init__(self, children):
        self.children = children

    def render(self, indent=''):
        inner = ''.join(child.render(indent + '\t') for child in self.children)
        return f'{indent}{self.open_tag}\n{inner}{indent}{self.close_tag}\n'

class Html(ContainingTag):
    '''HTML tag'''

    @property
    def open_tag(self): return '<!DOCTYPE html>\n<html>'
    
class Head(ContainingTag): '''HEAD tag'''

class Style(ContainingTag): '''STYLE tag'''

class Body(ContainingTag): '''BODY tag'''

class Div(ContainingTag): '''DIV tag'''

class P(SingleTag): '''P tag'''

Then:

html = Html([Div([Head([])])])
print(html)
<!DOCTYPE html>
<html>
    <div>
        <head>
        </head>
    </div>
</html>

Note: I’ve used \t as the per-level indent here, but you could use whatever makes sense for your needs.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading