Продолжаем перевод серии статей про аналоги в Python и JavaScript


В прошлых выпусках мы опирались на синтаксис классических версий Питона (2.7) и JS на основе ECMAScript 5. В этот раз мы будем использовать новые функции которые появились в Питоне 3.6 и JS стандарта ECMAScript 6.


ECMAScript 6 — относительно новый стандарт поддерживаемый большинством современных браузеров. Для использования стандарта 6 в старых браузерах вам понадобиться Babel для перевода современных конструкций JS6 на кросс-браузерную поддержку.


В сегодняшней статье: переменные в строках, распаковка списков, лямбда-функции, итерирование без индексов, генераторы и множества (sets).


Содержание других выпусков:


  1. Первая часть — приведение к типу, тернарный оператор, доступ к свойству по имени свойства, словари, списки, строки, конкатенация строк
  2. Вторая часть — сериализация словарей, JSON, регулярки, ошибки и исключения.

Переменные в строках


Традиционный способ построения строк с переменными использует конкатенацию строк и переменных:


name = 'World'
value = 'Hello, ' + name + '!\nWelcome!'

Такая запись может показаться разбросанной и плохочитаемой, также часто можно ошибиться в пробелах окружающих слова в строках.


Начиная с версии 3.6 в Питоне и в JS ECMAScrip6 вы можете использовать строковую интерполяцию, или, в терминах Питона — f-строки. Это строковые шаблоны в которых подставляются значения из переменных.


В Питоне f-строки помечаются символом f перед кавычками:


name = 'World'
value = f"""Hello, {name}!
Welcome!"""

price = 14.9
value = f'Price: {price:.2f} €'  # 'Price: 14.90 €'

В JS строковые шаблоны начинаются и кончаются обратной кавычкой (backtrick) `


name = 'World';
value = `Hello, ${name}!
Welcome!`;

price = 14.9;
value = `Price ${price.toFixed(2)} €`;  // 'Price: 14.90 €'

Заметим, что шаблоны могут быть как одно- итак и многострочными.
В Питоне можно задать форматирование переменных.


Распаковка списков


В Питоне, а теперь уже и в JS существует интересная возможность присвоить элементы последовательности различным переменным. К примеру, мы можем присвоить трем переменным три значения из списка:


[a, b, c] = [1, 2, 3]

Для кортежей скобки могут быть опущены.
Следующий пример очень популярен в Питоне как способ обмена значений двух переменных:


a = 1
b = 2
a, b = b, a   # поменяли значения

В JS6+ также возможно:


a = 1;
b = 2;
[a, b] = [b, a];  // поменяли значения

В Питоне, в случае если у нас есть неопределенное количество элементов в списке или кортеже, мы можем присвоить эти элементы кортежу из переменных в котором последние несколько значений вернуться как список:


first, second, *the_rest = [1, 2, 3, 4]
# first == 1
# second == 2
# the_rest == [3, 4]

Такое же можно сделать и в JS (ECMAScrip6):


[first, second, ...the_rest] = [1, 2, 3, 4];
// first === 1
// last === 2
// the_rest === [3, 4]

Лямбда-функции


И Питон и JS имеют довольно ясную функциональность для создания однострочных функций. Такие функции называются лямбда-функциями. Лямбды это такие функции которые принимают один или более аргументов и возвращают вычисленное значение. Обычно лямбда-функции используются когда нужно передать одну функцию в другую функцию в качестве колбека или в случае когда необходимо обработать каждый элемент последовательности.


В Питоне можно определить лямбда-функцию используя ключевое слово lambda:


sum = lambda x, y: x + y
square = lambda x: x ** 2

В JS используется => нотация. Если аргументов больше одного, они помещаются в скобки:


sum = (x, y) => x + y;
square = x => Math.pow(x, 2);

Итерация без индексов


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


for (i=0; i<items.length; i++) {
    console.log(items[i]);
}

Это не слишком красивая запись, и немного сложная для новичков — такая запись не выглядит естественно. В Питоне есть красивый лаконичный способ обхода списка:


for item in ['A', 'B', 'C']:
    print(item)

В современном JS такое реализуется при помощи оператора for..of:


for (let item of ['A', 'B', 'C']) {
    console.log(item);
}

Также можно обойти строку посимвольно в Питоне:


for character in 'ABC':
    print(character)

И в современном JavaScript:


for (let character of 'ABC') {
    console.log(character);
}

Генераторы


И Питон и современный JS позволяют определить специальные функции которые будут выглядеть как итераторы. При каждом вызове (итерации) они будут возвращать следующее сгенерированное значение из последовательности. Такие функции называются генераторы.


Генераторы обычно используют чтобы получить: числа из диапазона, строки из файла, данные постранично из внешнего API, числа фибоначчи и другие динамически генерируемые последовательности.


Технически генераторы выглядят как обычные функции, но вместо того чтобы вернуть одно значение (и прекратить работу), они выдают одно значение и приостанавливают работу до следующего вызова. Они будут генерировать следующие значения из списка при каждом вызове пока не будет достигнут конец списка.


Рассмотрим пример на Питоне в котором создается генератор countdown() который возвращает числа от заданного числа до 1 в обратном порядке (10,9,8,...,1):


def countdown(counter):
    while counter > 0:
        yield counter
        counter -= 1

for counter in countdown(10):
    print(counter)

То же самое можно получить в современном JS, но обратите внимание на * в описании функции. Это определяет ее как генератор:


function* countdown(counter) {
    while (counter > 0) {
        yield counter;
        counter--;
    }
}
for (let counter of countdown(10)) {
    console.log(counter);
}

Множества (Sets)


Мы уже познакомились со списками (lists), кортежами (tuples), массивами (arrays). Но есть еще один тип данных — множества (sets). Множества это массивы данных в котором каждый уникальный элемент присутствует только в единственном экземпляре. Теория множеств определяет с множествами такие операции как объединение(union), пересечение(intersection), и разность(difference), но мы не будем сейчас их рассматривать.


Создаем множество, добавляем в него элемент, проверяем существование элемента, получаем общее количество элементов, обходим множество по элементам и удаляем один элемент используя Питон:


s = set(['A'])
s.add('B'); s.add('C')
'A' in s
len(s) == 3
for elem in s:
    print(elem)
s.remove('C')

То же самое на JS:


s = new Set(['A']);
s.add('B').add('C');
s.has('A') === true;
s.size === 3;
for (let elem of s.values()) {
    console.log(elem);
}
s.delete('C')

Подытожим


  • Строковые шаблоны (f-строки) позволяют улучшить читаемость и упростить код, даже в случае многострочных объектов.
  • Можно обходить массивы, группы или строки без использования индексов.
  • Используя генераторы можно получить последовательности с практически неограниченным числом элементов.
  • Использование множеств упрощает проверку уникальности элемента в массиве.
  • Используйте лямбды когда вам нужны небольшие однострочные функции.

В следующей части поговорим об аргументах функций, классах, наследовании и свойствах.

Комментарии (8)


  1. JiLiZART
    27.07.2018 00:01

    Есть замечательный сайт который описывает все языковые конструкции на разных языках http://hyperpolyglot.org/


    1. vzhicharra Автор
      27.07.2018 01:28

      Интересный сайт, спасибо.
      Правда как там выбрать конкретные языки и посмотреть на аналогичные конструкции я так и не понял. Сравнивать там можно только по предустановленным авторами наборам языков.


  1. k12th
    27.07.2018 00:31

    в терминах Питона — f-строки

    А зачем они? Там же с незапамятных времен есть some_string_with_tokens % some_dict_with_values...


    1. vzhicharra Автор
      27.07.2018 01:25
      +1

      В Питоне масса способов форматирования строк.
      f-строки больше для шаблонов с подстановками, также возможно производить действия, вызывать функции обращаться к элементу прямо внутри {}


    1. Crandel
      27.07.2018 08:40

      f-строки быстрее всех других способов. Только ими и пользуемся во всех проектах


  1. BubaVV
    27.07.2018 12:07

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

    for key in instance: ...


  1. x-foby
    29.07.2018 01:45
    +1

    for (i=0; i<items.length; i++) {
        console.log(items[i]);
    }
    

    Это не слишком красивая запись, и немного сложная для новичков — такая запись не выглядит естественно


    Это мы, конечно, приехали. Итераторы, генераторы, спреды, регулярки — это для новичков самое то, а старый-добрый for — это не красиво, немного сложно и неестественно)
    Ещё, пожалуй, стоит оградить новичков от while, а то не приведи господь им узнать, что в этом цикле можно остаться навсегда))

    ЗЫ: это не претензия, и уж тем паче не к автору ПЕРЕВОДА)
    Просто забавно))


    1. vzhicharra Автор
      29.07.2018 01:51

      а старый-добрый for

      Это для тех кто с С-подобных языков начинал – тем да, старый, добрый.
      А тем кто с Питона начал — тем такая конструкция может показаться непонятной, тем более что в Питоне такого for'а нет, надо придумывать свою итерацию по счетчику.
      Эта серия — для начинающих питонистов чтоб они могли читать js-код.