Я бы сказал, что первая ошибка — это попытка написать статически типизированный код на динамическом языке.
Не стесняйтесь использовать идентификатор, чтобы указать на строку, а затем список в автономных разделах кода.
keys = 'foo bar foobar' # Imagine this coming in as an argument
keys = keys.split() # Now the semantically chose name for the argument can be
# reused As the semantically chosen name for a local variable
не стесняйтесь относиться к функциям как к обычным значениям: так оно и есть. Возьмем следующий парсер. Предположим, что мы хотим обрабатывать все теги заголовков одинаково, а теги ul — как теги ol.
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):
# generic code
def parse_header(self, attrs):
# more generic code
parse_h1 = parse_h2 = parse_h3 = parse_h4 = parse_h5 = parse_h6 = parse_header
parse_ol = parse_ul = parse_list
Это можно сделать, используя менее общий код в методе handle_starttag
на таком языке, как java, отслеживая, какие теги сопоставляются с одним и тем же методом, но затем, если вы решите, что хотите обрабатывать теги div, вы должны добавить это в диспетчеризацию. логика. Здесь вы просто добавляете метод parse_div
, и все готово.
Не проверяйте тип! Утиный тип!
def funtion(arg):
if hasattr(arg, 'attr1') and hasattr(arg, 'attr2'):
foo(arg):
else:
raise TypeError("arg must have 'attr1' and 'attr2'")
в отличие от isinstance(arg, Foo)
. Это позволяет передать любой объект с attr1
и attr2
. Это позволяет вам, например, передать класс трассировки, обернутый вокруг объекта, для целей отладки. Вам нужно будет изменить класс, чтобы сделать это в Java AFAIK.
Как указывает THC4k, другим (более питоническим) способом сделать это является EAPF идиома. Мне это не нравится, потому что я люблю ловить ошибки как можно раньше. Это более эффективно, если вы ожидаете, что код будет редко давать сбои. Не говорите никому, что мне это не нравится, хотя они перестанут думать, что я умею писать на питоне. Вот пример, любезно предоставленный THC4k.
try:
foo(arg):
except (AttributeError, TypeError):
raise InvalidArgumentError(foo, arg)
Вопрос в том, должны ли мы ловить AttributeError
и TypeError
или просто позволить им распространяться туда, где они знают, как с ними обращаться, но это всего лишь пример, поэтому мы позволим ему летать.
person
aaronasterling
schedule
13.09.2010