# Understanding polymorphism in Python

I feel like I don't understand how polymorphism works in Python. Here is something I put together.

class _Tag(object):
def __init__(self):
#DisjointedTag and JoinedTag will bypass __init__.
#Also, self will not be defined within this class.
#Bottom line, this class is just for inheritance.
raise NotImplementedError;

def join_attributes(self):
self.joined_pieces=''.join(self.funct_pieces);
self.__class__=JoinedTag;

def to_disjointed(self):
self.__class__=DisjointedTag;

def add_attribute(self, attribute, value):
self.funct_pieces.insert(
-1, ' {}="{}"'.format(attribute, value)
);
self.to_disjointed();

class Tag(_Tag):
def __init__(self, name):
self.funct_pieces=[
i.format(name) for i in ['<{0}', '>{{}}</{0}>']
];
self.joined_pieces='';

def __call__(self, contents):
self.join_attributes();
return self(contents);

class JoinedTag(_Tag):
def __call__(self, contents):
return self.joined_pieces.format(contents);

class DisjointedTag(_Tag):
#JoinedTag.__call__ has 1 mandatory parameter so this also needs one.
def __call__(self, place_holder):
raise TypeError(
'{} is disjointed because attributes were added to it.'.\
format(self)
);


Here is an example:

>>> p=Tag('p')
>>> p('hi')
'<p>hi</p>'
>>> p.add_attributes('align', 'left')
>>> p.join_attributes();
>>> p('hi')
'<p align="left">hi</p>'


I could have joined the attributes on every call but that would waste time. The code I made has no if statements, so it should be more readable according to the philosophy of polymorphism. However, it is very hard to read. I figure I've done something wrong or I'm not used to reading polymorphic code.

• I get SyntaxError: invalid syntax when I try to run your code. At Code Review we review working code. – Gareth Rees Dec 23 '13 at 21:34
• The add_attribute method definition is missing a def keyword. – Iguananaut Dec 23 '13 at 21:56
• Sorry, I fixed the errors I made typing the question. – user1411571 Dec 23 '13 at 21:58
• I think what you're doing is overkill. Although it is possible to modify self.__class__ that way lies dragons. Do you really need separate classes for JoinedTag and DisjointededTag? A flag would seem fine. – Iguananaut Dec 23 '13 at 21:59
• If you have problems with understanding polymorphism in python it seems to me that CR is the wrong place to ask. Maybe you should have a try at StackOverflow or programmers.SE? – Nobody moving away from SE Dec 23 '13 at 23:11

## 1 Answer

I'm a bear of very little brain, so I don't really understand what you are trying to achieve, or why you think polymorphism will help you achieve it.

But I did notice some problems with your code:

1. There's no documentation.

2. There are no test cases.

3. Python doesn't need semicolons at the end of lines.

4. You don't need a \ at the end of a line if the statement cannot end at that point because of an unclosed parenthesis.

5. There are no checks on the validity of entity and attribute names.

6. Values aren't escaped.

7. There's no check to stop the caller adding multiple attributes with the same name.

8. You shouldn't raise an exception class, you should raise an instance of that class (passing a suitable error message to the constructor).

• The semicolons are just my personal preference. Polymorphism was a challenge I imposed on myself but it was not suitable for the task. What do you mean test cases? – user1411571 Dec 23 '13 at 23:05
• Very few Python programmers use semicolons like that (it's a sign that someone is not fluent in the language), so if you insist on using them you'll find it a barrier to collaboration. As for test cases, see Wikipedia. – Gareth Rees Dec 23 '13 at 23:12