2010-09-13 3 views
6

Что такое верхняя страница для кого-то, перемещающегося из статического lang (java/C#) в динамический язык, такой как python?top gotchas для кого-то, перемещающегося из статического lang (java/C#) в динамический язык, такой как python

Кажется здоровым, как все может быть сделано, но переименование метода или добавление/удаление параметров кажется настолько рискованным!

Является единственным решением для написания тестов для каждого метода?

ответ

2

Я бы сказал, что номер один получил, чтобы написать статически типизированный код на динамическом языке.

, не стесняйтесь использовать идентификатор, чтобы указать на строку, а затем список в автономных участков кода

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 или просто позволить им распространяться куда-то, что знает, как обращаться с ними, но это всего лишь пример, поэтому мы дадим ему лететь.

+0

@ THC4k. Как вы говорите, что это странно? Если 'type (Foo)' не является подклассом 'type', который превышает атрибут' __instancecheck__', 'isinstance' зависит от местоположения в иерархиях классов. То, что я представил, не разделяет этот недостаток. LBYL против EAFP - еще одна проблема. Я забыл включить другой стиль. – aaronasterling

+0

'if hasattr (arg, 'attr1') и hasattr (arg, 'attr2')' является typecheck. Он проверяет, принадлежит ли arg к (неявному) классу «вещей, которые имеют атрибут attr1 и attr2». Это * более общее, что использование 'isinstance', которое проверяет только один тип, а не целый класс типов. Но эти проверки часто не нужны: просто сделайте foo (arg) сразу, посмотрите, что происходит и поймайте Исключения, где это имеет смысл. Пусть Python выполнит все typechecks для вас - если foo (arg) не имеет смысла, он в конечном итоге исключит исключение. –

+0

@aaronasterling извините, да, плохая формулировка, я переписывал комментарий. –

3

"Is the only solution to write tests for each method?"

Вы говорите, вы не тесты записи для каждого метода в Java?

Если вы написали тесты для каждого метода на Java, тогда - ну ничего не изменилось, не так ли?

renaming a method, seems so risky!

Исправить. Не делай этого.

adding/removing parameters seems so risky!

Что? Вы говорите о дополнительных параметрах? Если это так, то наличие нескольких перегруженных имен в Java кажется рискованным и запутанным. Наличие дополнительных параметров кажется более простым.


Если вы ищете SO для самых распространенных вопросов Python, вы обнаружите, что некоторые вещи являются хроническими вопросами.

  • Как обновить PYTHONPATH.

  • Почему некоторый случайный расчет с плавающей запятой не совпадает с математической абстракцией.

  • Использование Python 3 и ввод кода из учебника Python 2.

  • Почему Python не имеет суперкомплексора protected, private и public объявлений.

  • Почему у Python нет типа перечисления.

# 1 хроническая проблема, кажется, использует изменяемые объекты в качестве значений по умолчанию для функции. Просто избегайте этого.

+2

Мне редко приходилось возиться с PYTHONPATH. И ни один из них не является языковой проблемой с плавающей точкой, каждый из них (независимо от того, стоит ли Java или C# или ... или даже Scheme) его соли, знает это. В противном случае, согласился. – delnan

+3

@ delnan: Вы можете не испортить его, но есть удивительное количество вопросов SO по этому вопросу. Кроме того, проблема с плавающей точкой должна быть хорошо известна. Тем не менее ... Удивительно ... SO полна вопросов «2.1 + 3.2! = 5.3». –

+3

Хорошо, поэтому некоторые люди не получают пути поиска импорта и числа с плавающей запятой - но это потому, что они исходят из статического языка? Скорее всего, нет - плавающие точки работают одинаково на каждом языке, и, по крайней мере, у java похоже что-то похожее на 'PYTHONPATH',' CLASSPATH' (исправьте меня, если я ошибаюсь, я не парень Java). – delnan

2

Некоторые вещи, которые поразили меня, когда первый попробовать Python (идущий от в основном Java фон):

  1. Запись Pythonic код. Используйте идиомы, рекомендованные для Python, вместо того, чтобы делать это старым способом Java/C. Это больше, чем просто косметическая или догматическая проблема. Pythonic-код на самом деле на практике намного быстрее, чем C-подобный код практически все время. На самом деле, IMHO очень сильно игнорирует понятие «Python slow», потому что неопытные кодеры пытались кодировать Java/C в Python и в итоге получили большой успех и получили представление о том, что Python ужасно медленно. По возможности используйте списки и карту/фильтр/сокращение.

  2. Удовлетворитесь тем, что функции действительно являются объектами. Передавайте их как обратные вызовы, возвращайте функции функции, узнайте о закрытии и т. Д.

  3. Есть много интересных и почти магических вещей, которые вы можете использовать в Python, например, как переименование. Эти вещи великолепны, чтобы показать возможности Python, но на самом деле не нужны, если они вам не нужны. Действительно, как отметил С. Лотт, лучше избегать вещей, которые кажутся рискованными.

+1

Python ** ** медленнее. Заказы величины медленнее. Но это не имеет значения. Отчасти потому, что идиоматический код не * * * медленный, отчасти потому, что мы не делаем raytracers в Python.Кроме того, классный материал, который делает язык настолько медленным, также полностью компенсирует потерю производительности. – delnan

+0

@ delnan. Я видел, как itertools избили чистый код C на 20 секунд или около того на восьмидесятиминутную задачу;) – aaronasterling

+1

@aaronasterling: Разве itertools не является библиотекой C? (Я мог ошибаться) – Daenyth