Аналоги в Python и JavaScript. Часть первая

Привет, Хабр! Представляю вашему вниманию перевод статьи "Equivalents in Python and JavaScript. Part 1".


Несмотря на то что Python и Javascript довольно сильно отличаются, существует много схожего, о чем должен знать любой фулстек разработчик. В этой серии из 4-х статей мы увидим что есть общего в обоих языках, и рассмотрим ряд известных проблем а также способы их решения.


Это не справочник, здесь не будет базовой информация о типах переменных, if-ах и циклах.
Но мы рассмотрим более сложные структуры данных и операции с ними используя Python и Javascript.


Также я проиллюстрирую это примерами из практики.


Эта серия будет интересна бэкендерам, использующим Django, Flask или любой другой Python-фреймворк, которые хотят получше узнать о современном Javascript'е. С другой стороны, эти статьи будут полезны фронтендерам, которые желают лучше понять как работает бэкенд, или даже написать свой сайт на Django.


Остальные статьи в этой серии:


  1. Часть вторая: JSON, регулярки, ошибки-исключения
  2. Часть третья: современные Python и JS: строковые шаблоны (f-строки), распаковка списков, лямбда-функции, итерации по спискам, генераторы, множества.
  3. Четвертая часть — аргументы функций, создание и работа с классами, наследование, геттеры-сеттеры и свойства класса.

Приведение к типу


Начнем с приведения строки к целому. В Питоне все просто и прямолинейно:


number = int(text)

Но в JS вы должны объяснить к какой системе вы собираетесь приводить — к десятеричной, восьмеричной, шестнадцатеричной или двоичной:


number = parseInt(text, 10);

Для использования обычной десятеричной системы мы передаем 10 в виде второго аргумента функции parseInt(). 8 для восьмеричной, 16 для шестнадцатеричной или 2 — для двоичной. В случае если второй параметр опущен, число начинается с нуля и вы используете устаревший браузер, строка с текстом будет воспринята как восьмеричная система:


parseInt('012') == 10  // в некоторых старых браузерах
parseInt('012', 10) == 12

Условное присваивание


Хотя для этого Python и JS используют различный синтаксис, данная операция популярна в обоих языках. Популярна она потому, что в одном выражении можно присвоить различные значения как для True-, так и для False-случая.
Начиная с Python 2.7 условное присваивание выглядит так:


value = 'YES' if positive == True else 'NO'

В JavaScript условное присваивание производится с использованием тернарного оператора ?, также как в C, C++, C#, Java, Ruby, PHP, Perl, Swift, and ActionScript:


value = positive === true? 'YES': 'NO';

Доступ к свойству объекта по имени свойства


Обычный способ доступа к свойству объекта и в Python и в JS одинаковый:


obj.color = 'YELLOW'

А как быть если название свойства заключено в строчную переменную? К примеру, название свойства может быть получено из списка свойств или название свойства составлено из двух строковых переменных: "title" + land_code.
В Питоне для этого существуют функции getattr() и setattr():


attribute = 'color'
value = getattr(obj, attribute, 'GREEN')
setattr(obj, attribute, value)

В JS вы можете обращаться с объектом как со словарем и передавать имя свойства в квадратных скобках:


attribute = 'color';
value = obj[attribute] || 'GREEN';
obj[attribute] = value;

Чтобы получить значение по умолчанию в случае если свойства с таким именем не существует, в Питоне у функции getattr() есть для этого третий параметр. В JS, если запрашиваемое свойство отсутствует, функция вернет undefined. Его можно сравнить оператором OR со значением по дефолту – это стандартная практика в JS — такой способ можно встретить во многих фреймворках и библиотеках.


Доступ к словарю по ключу


Схоже с вышеизложенным. Ключ стандартно указывается в квадратных скобках в обоих языках:


dictionary = {}
dictionary['color'] = 'YELLOW'

Для доступа по ключу в Питоне используется стандартный синтаксис с квадратными скобками, однако в случае если такой ключ отсутствует это вызовет исключение с ошибкой KeyError.
Более гибким является метод get() который вернет None в случае отсутствия ключа. Также можно передать значение которое будет возвращено в случае отсутствия ключа:


key = 'color'
value = dictionary.get(key, 'GREEN')

В JS вы можете проделать такой же трюк как со свойством объекта – OR со значением по дефолту:


key = 'color';
value = dictionary[key] || 'GREEN';

Срезы: списки и строки


У Питона есть оператор [:] получения части списка, кортежа или схожих структур. Пример с объектом типа Django QuerySets:


items = [1, 2, 3, 4, 5]
first_two = items[:2]      # [1, 2]
last_two = items[-2:]      # [4, 5]
middle_three = items[1:4]  # [2, 3, 4]

У JS есть метод slice() с тем же эффектом:


items = [1, 2, 3, 4, 5];
first_two = items.slice(0, 2);     // [1, 2] 
last_two = items.slice(-2);        // [4, 5]
middle_three = items.slice(1, 4);  // [2, 3, 4]

Но не путайте с методом splice() который изменяет исходный массив!


В Питоне оператор [:] также применим и к строкам:


text = 'ABCDE'
first_two = text[:2]      # 'AB'
last_two = text[-2:]      # 'DE'
middle_three = text[1:4]  # 'BCD'

В JS у строк также есть метод slice():


text = 'ABCDE';
first_two = text.slice(0, 2);    // 'AB'
last_two = text.slice(-2);       // 'DE'
middle_three = text.slice(1, 4); // 'BCD'

Операции со списками


В программировании часто приходится собирать и анализировать последовательность элементов. В Питоне для этого обычно используют списки, а в Javascript — массивы. У них схожий синтаксис и операции, но различаются методы добавления и удаления элементов.


Соединяем два списка, добавляем один элемент в конец, добавляем один элемент в начало, получаем и удаляем элемент в начале, получаем и удаляем элемент с конца и удаляем конкретный элемент по индексу.
Python:


items1 = ['A']
items2 = ['B']
items = items1 + items2  # items == ['A', 'B']
items.append('C')        # ['A', 'B', 'C']
items.insert(0, 'D')     # ['D', 'A', 'B', 'C']
first = items.pop(0)     # ['A', 'B', 'C']
last = items.pop()       # ['A', 'B']
items.delete(0)          # ['B']

То же в Javascript:


items1 = ['A'];
items2 = ['B'];
items = items1.concat(items2);  // items === ['A', 'B']
items.push('C');                // ['A', 'B', 'C']
items.unshift('D');             // ['D', 'A', 'B', 'C']
first = items.shift();          // ['A', 'B', 'C']
last = items.pop();             // ['A', 'B']
items.splice(0, 1);             // ['B']

Соединяем наборы строк


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


В Питоне для этого служит строковый метод join() который принимает в виде аргумента список или кортеж. Для непосвященного (в синтаксис Питона) может показаться странным начинать выражение с разделителя, но, после регулярного применения вы привыкнете к такой форме записи:


items = ['A', 'B', 'C']
text = ', '.join(items)  # 'A, B, C'

В JS у массивов есть метод join() с разделителем в виде аргумента:


items = ['A', 'B', 'C'];
text = items.join(', ');  // 'A, B, C'

Подытожим


  • Списки (lists) и кортежи (tuples) в Python соответствуют массивам (arrays) в Javascript.
  • Словари (dictionaries) в Python соответствуют объектам (objects) в Javascript.
  • Строки в Питоне похожи на строки в Javascript.
  • Приводить строку к числу в Javascript нужно с осторожностью, помня о системах счисления.
  • Однострочные условные выражения существуют в ооих языках.
  • Объединение последовательностей строк (' '.join) в Питоне обескураживает непосвященного в синтаксис, но к нему быстро привыкаешь.

В следующей серии мы посмотрим на создание и парсинг JSON, регулярные выражения и работу с ошибками и исключениями!

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 13

    +5
    Ну ок, а в чём смысл то?
      0
      Начинающим, но уже освоившим один язык — некий быстрый старт для смежного языка.
      По большей части синтаксис интуитивно понятен, но некоторые моменты частенько вгоняют в ступор, как например join в Питоне
      +1
      Условное присвоение? Это обычное присвоение + тренарный оператор.
        +2
        тренарный

        тернарный
        +2
        Начнем с приведения строки к целому. В Питоне все просто и прямолинейно:

        number = int(text)

        Но в JS вы должны объяснить к какой системе вы собираетесь приводить...

        Настолько просто и прямолинейно, что второй аргумент основания системы счисления является именованным и имеет значение по умолчанию:

        number = int(text, base=10)
          0
          key = 'color';
          value = dictionary[key] || 'GREEN';
          

          Если по ключу вернется значение 0 или "" (пустая строка), то оно интерпретируется как false и тогда вернется 'GREEN'. Но сдается мне, что в некоторых ситуациях мы будем ожидать именно 0 или пустую строку.
          Как мне кажется, лучшим подходом было бы проверить именно на undefined
          key = 'color';
          value = dictionary[key] !== undefined ?  dictionary[key] : 'GREEN';
          
            +4

            … но в некоторых случаях мы будем ожидать именно undefined (почему нет?), и лучшим подходом будет проверка через in:


            key in dictionary ?  dictionary[key] : 'GREEN';
            0
            > В JS вы можете проделать такой же трюк как со свойством объекта – OR со значением по дефолту
            В питоне такое тоже работает:
            >>> a = None
            >>> b = a or 'GREEN'
            >>> b
            'GREEN'

              0
              Тут имелось в виду что в Питоне есть стандартный метод получения значения из словаря по отсутствующему_ключу — get(key, default_value) — а в JS для такого надо городить небольшой костыль в виде OR, который стал де-факто стандартной практикой.
              Вообще же в любом языке (ну за исключением может быть какой-то экзотики) сравнение нуля/Null/None/False OR что_то_отличное_от_нуля — всегда дает это_что_то
                0
                Не согласен про экзотику. В любом сильно-типизированном языке (c, cpp, java) логический OR может вернуть только bool.
                  0

                  Но в C и C++ типизация слабая (неявная), т.к. там есть неявные преобразования типов. В Питоне же она как раз сильная.

                    0
                    Вы правы насчет слабой в С\С++, но утверждают, что она там явная (кроме auto с C++11). Вообще там черт ногу сломит в определениях… Я хотел сказать, что в этих трех языках точно не получится провернуть трюк с OR, и уж точно их нельзя назвать экзотикой.
              0
              items = items1.concat(items2);

              если уже говорить о различных подходах в языках, то стоит, наверное, упомянуть и возможность сделать вот так:
              items = [...items1, items2]

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое