Я бы сказал, что номер один получил, чтобы написать статически типизированный код на динамическом языке.
, не стесняйтесь использовать идентификатор, чтобы указать на строку, а затем список в автономных участков кода
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
, и вам хорошо идти.
Не проверяйте тип! Duck-type!
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, другой (более pythonic) способ сделать это - идиома EAPF. Мне это не нравится, потому что мне нравится ломать ошибки как можно раньше. Это более эффективно, если вы ожидаете, что код будет редко выходить из строя. Не говорите никому, мне это не нравится, хотя мы перестанем думать, что я знаю, как писать питон. Вот пример любезности THC4k.
try:
foo(arg):
except (AttributeError, TypeError):
raise InvalidArgumentError(foo, arg)
Это tossup, чтобы, если мы должны поймать AttributeError
и TypeError
или просто позволить им распространяться куда-то, что знает, как обращаться с ними, но это всего лишь пример, поэтому мы дадим ему лететь.
@ THC4k. Как вы говорите, что это странно? Если 'type (Foo)' не является подклассом 'type', который превышает атрибут' __instancecheck__', 'isinstance' зависит от местоположения в иерархиях классов. То, что я представил, не разделяет этот недостаток. LBYL против EAFP - еще одна проблема. Я забыл включить другой стиль. – aaronasterling
'if hasattr (arg, 'attr1') и hasattr (arg, 'attr2')' является typecheck. Он проверяет, принадлежит ли arg к (неявному) классу «вещей, которые имеют атрибут attr1 и attr2». Это * более общее, что использование 'isinstance', которое проверяет только один тип, а не целый класс типов. Но эти проверки часто не нужны: просто сделайте foo (arg) сразу, посмотрите, что происходит и поймайте Исключения, где это имеет смысл. Пусть Python выполнит все typechecks для вас - если foo (arg) не имеет смысла, он в конечном итоге исключит исключение. –
@aaronasterling извините, да, плохая формулировка, я переписывал комментарий. –