Чтение кода на Python

У меня есть опыт программирования со статически типизированными языками. Теперь, пишу код в Python, я испытываю трудности с его удобочитаемостью. Допустим, у меня есть класс Host:

class Host(object):
  def __init__(self, name, network_interface):
    self.name = name
    self.network_interface = network_interface

Я не понимаю из этого определения, что такое "network_interface". Это строка, например "eth0", или это экземпляр класса NetworkInterface? Единственный способ, который я собираюсь решить, - документировать код с помощью "docstring". Что-то вроде этого:

class Host(object):
  ''' Attributes:
      @name: a string
      @network_interface: an instance of class NetworkInterface'''

Или могут быть соглашения об именах для таких вещей?

Ответы

Ответ 1

Использование динамических языков научит вас чему-то статичным языкам: вся помощь, которую вы получили от статического языка, который вы сейчас пропустили на динамическом языке, не все это было полезно.

Чтобы использовать ваш пример, на статическом языке вы должны знать, что параметр был строкой, а в Python - нет. Поэтому в Python вы пишете docstring. И пока вы пишете это, вы понимаете, что вам нужно больше сказать об этом, чем "это строка". Вы должны сказать, какие данные находятся в строке, и какой формат она должна иметь, и что такое по умолчанию, и что-то об условиях ошибки.

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

Ответ 2

Соглашения docstring находятся в PEP 257.

В этом примере используется этот формат для указания аргументов, вы можете добавить типы, если они имеют значение:

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    Keyword arguments:
    real -- the real part (default 0.0)
    imag -- the imaginary part (default 0.0)

    """
    if imag == 0.0 and real == 0.0: return complex_zero
    ...

Был также отклоненный PEP для docstrings для атрибутов (а не аргументов конструктора).

Ответ 3

Самое пифоническое решение - документировать с примерами. Если возможно, укажите, какие операции должен поддерживать объект, а не конкретный тип.

class Host(object):
  def __init__(self, name, network_interface)
    """Initialise host with given name and network_interface.

    network_interface -- must support the same operations as NetworkInterface

    >>> network_interface = NetworkInterface()
    >>> host = Host("my_host", network_interface)

    """
    ...

На этом этапе подключите ваш источник до doctest, чтобы убедиться, что ваши примеры документов продолжают работать в будущем.

Ответ 4

Лично я нашел очень полезным использовать pylint для проверки моего кода.

Если вы будете следовать подсказке pylint почти автоматически, ваш код станет более читаемым, вы улучшите свои навыки написания питона, соблюдаете соглашения об именах. Вы также можете определить свои собственные соглашения об именах и т.д. Это очень полезно специально для начинающего питона.

Я предлагаю вам использовать.

Ответ 5

Python, хотя и не так явно набирается как C или Java, все еще печатается и будет генерировать исключения, если вы делаете что-то с типами, которые просто не играют хорошо вместе.

С этой целью, если вы обеспокоены тем, что ваш код правильно используется, поддерживаются правильно и т.д., просто используйте docstrings, комментарии или даже более явные имена переменных, чтобы указать, какой тип должен быть.

Еще лучше, включите код, который позволит ему обрабатывать любой тип, который может быть передан, пока он дает полезный результат.

Ответ 6

Одним из преимуществ статической типизации является то, что типы являются формой документации. При программировании на Python вы можете документировать более гибко и плавно. Конечно, в вашем примере вы хотите сказать, что network_interface должен реализовывать NetworkInterface, но во многих случаях тип является очевидным из контекста, имени переменной или по соглашению, и в этих случаях, опустив очевидное, вы можете создать более читаемый код. Общим является описание значения параметра и неявное предоставление типа.

Например:

def Bar(foo, count):
    """Bar the foo the given number of times."""
    ...

Это описывает функцию кратко и точно. То, что означает foo и bar, будет очевидным из контекста, и что count является (положительным) целым, является неявным.

В вашем примере я бы просто упомянул тип в строке документа:

"""Create a named host on the given NetworkInterface."""

Это более короткое, более читаемое и содержит больше информации, чем список типов.