I would say that the resulting number one tries to write statically typed code in a dynamic language.
Feel free to use an identifier to point to a string and then a list in standalone sections of code
keys = 'foo bar foobar'
Feel free to consider functions like ordinary values: they are. Take the following parser. Suppose we want to process all header tags, as well as ul tags, such as ol tags.
class Parser(HTMLParser): def __init__(self, html): self.feed(html) def handle_starttag(self, tag, attrs): parse_method = 'parse_' + tag if hasattr(self, parse_method): getattr(self, parse_method)(attrs) def parse_list(self, attrs):
This can be done using less generic code in a handle_starttag method in a language such as java, tracking which tags map to the same method, but if you decide you want to process div tags, you must add this to the dispatch logic. Here you just add the parse_div method and you are good to go.
Do not use typecheck! Duck-type!
def funtion(arg): if hasattr(arg, 'attr1') and hasattr(arg, 'attr2'): foo(arg): else: raise TypeError("arg must have 'attr1' and 'attr2'")
unlike isinstance(arg, Foo) . This allows you to pass any object using attr1 and attr2 . This allows you, for example, to pass a trace class wrapped around an object for debugging purposes. You will need to change the class to do this in Java AFAIK.
As pointed out by THC4k, another (more pythonic) way to do this is through the EAPF idiom. I donβt like it because I like breaking errors as early as possible. This is more efficient if you expect code to rarely fail. Do not tell anyone, I do not like it, although we will stop thinking that I know how to write python. Here is an example courtesy of THC4k.
try: foo(arg): except (AttributeError, TypeError): raise InvalidArgumentError(foo, arg)
This is what we need if we need to catch AttributeError and TypeError or just let them spread somewhere who knows how to handle them, but this is just an example, so we will let it fly.