Рубрики
Без рубрики

Python Gotchas для JavaScript разработчиков

Если вы разработчик JavaScript, который заинтересован в темах, таких как машинное обучение, наука о данных или … с меткой Python, JavaScript, CodeNewie.

Если вы разработчик JavaScript, который заинтересован в темах, таких как машинное обучение, наука о данных или даже если вы хотите узнать новый инструмент, чтобы расширить свой опыт, есть высокий шанс, что вы пытаетесь (или попробовать) Python. Пока оба языка очень похожи, есть куча удивительных различий, которые могут спутать вас. В этой статье я перечислю пару таких балансов вместе с примерами и объяснениями, которые помогут вам понять, почему оба языка ведут себя по-разному.

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

Анонимные функции очень ограничены

Сначала в списке: анонимные функции aka закрывают aka лямбдас. Они очень распространенный инструмент в JavaScript. Быть справедливым, они не имеют ничего особенного, просто созданные функции AD-HOC, которые не имеют никакого конкретного имени. В любое время вы пишете Array.map ((EL) => Дозметие (EL)) Вы пишете анонимную функцию. HECK, чтобы быть справедливым, вероятно, 99% функций JS вы пишете в эти дни технически анонимными. Посмотри на это:

const myFun = () => alert("I have no name!");
const otherFun = function() { alert("Me neither!"); }

Эти 2 функции являются анонимными. Вы можете обратиться к ним через переменную, на которую они назначены, но если эта переменная когда-либо меняет значение, вы не можете найти функцию снова, она потеряна. Для того, чтобы иметь «реальную» названную функцию, вам нужно сделать это:

function myFun() { alert("I have a name"); }

class MyClass {
    otherFun() { alert("Me too!"); }
}

Существуют определенные другие различия между именами и анонимными функциями в JS, но в целом они очень похожи, и вы можете легко использовать любой из них большую часть времени. Однако в Python ситуация отличается. В то время как язык поддерживает как именованные, так и анонимные функции, последние очень ограничены: они могут состоять только из одного выражения (по сути, они могут сделать одну операцию). Чтобы показать вам пример:

fun1 = lambda : print("works!")
fun2 = lambda a, b : a + b

wrongFun = lambda: # this will throw invalid syntax error!
    a = 1
    b = 2
    return a + b

Это означает, что следующий кусок кода невозможно написать с помощью лямбдаса в Python:

makeRequest().then((result) => {
    logOutput(result.data);
    saveContent(result.data["content"]);
    return result;
}); 

Почему там такое ограничение? Как Сам Создатель Питона объясняет :

Я нахожу любой Решение неприемлемо, которое встраивает блок на основе отступа в середине выражения. Поскольку я нахожу альтернативный синтаксис для группировки операторов (например, брекеты или ключевые слова начнется/заканчивается) одинаково неприемлемым, это в значительной степени делает многострочный лямбда неразрешимой головоломкой.

В основном для того, чтобы разрешить многострочные анонимные функции, одно выражение необходимо уважать правила на основе вкладок (в настоящее время не следует) или использовать другие разделители блока (например {} в JS). Гвидо Ван Россум, создатель языка, отклонил обе эти идеи.

Что такое решение тогда? Ну просто дайте функцию имя! Чтобы быть справедливым, это не то, что большая часть сделки, скорее неудобства, но и чта, то, что я не ожидал, когда я впервые узнал Python.

Выражения против утверждений

С предыдущим пунктом различия между утверждениями и выражениями на обоих языках. Если вы не уверены, какие эти два, краткое объяснение – это то, что выражение – это то, что производит значение, а оператор – это просто кусок кода, который что-то выполняет, но не возвращает никакого значения. Другими словами, вы можете спросить себя: Могу ли я назначить его переменной? Если да, это выражение, в противном случае это утверждение Отказ Например:

const a = 3; // 3 is an expression
const b = a + 12; // arithmetic operations are expressions
const c = (z = 10); // (z = 10) is also an expression
const d = (if (a > 2) { 7 } else { 2 }); // this won't work! if is a statement

function myFun() { alert("alert"); }
const e = myFun(); // calling a function is an expression

Хорошо, так в чем вопрос? Ну, проблема в том, что выражение в JavaScript может не быть выражением в Python! Например, создание функции:

const something = () => 8;
const sthElse = function namedFun() { return 7; } 

Этот код совершенно действителен в JavaScript (даже если не распространено для назначения именованных функций для переменных). А как насчет Python?

something = lambda : 8; # this code is valid
sthElse = def namedFun(): return 7; # this code will crash!

В этом случае 2-й пример не работает, потому что определение именованной функции в Python является утверждением, а не выражением. Точно так же с заданиями Пусть в JS возвращает 10 , пока в Python А Ничего не возвращается, он не дает никакого значения.

Я не уверен, почему определение функции Python является утверждением. Возможное объяснение заключается в том, что в одной руке строки в отступе внутри выражения не создают новую область (что логично, почему они) и, с другой – определение функции рук должно создать новый объем, поэтому определение функции не может быть выражение. Это просто моя теория, может быть, было решено, что априори, что определение – это утверждение, и это.

Я не могу придумать больше диффунтовки между выражениями и операторами в Python VS JavaScript, но если вы заинтересованы в том, как он смотрит на других языках, вы можете проверить Ruby, где по существу все – это выражение (в том числе если , для и т. Д.).

Хитрые параметры по умолчанию

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

const processJob = (name, args, delay = 0) {
    Job.fetchByName(name).startIn(delay).execute(args)
}

processJob("createUser", {name: "Ian"}, 60) // run in 60sec
processJob("createUses", {name: "Ion"}) // run now

В Python значения по умолчанию имеют улов, хотя – вместо того, чтобы быть оцененным каждый раз, когда вызывается функция, Значения по умолчанию оцениваются только один раз Отказ Почему это имеет значение? Потому что, если вы решите изменять аргумент внутри вашей функции, он не будет возвращен к своему предыдущему состоянию! Позвольте мне показать это, используя пример. Во-первых, JavaScript:

const addOne = (ary = []) => {
    ary.append(1);
    return ary;
}

addOne([3,2]); // returns [3,2,1]
addOne([3,2]); // returns [3,2,1] again

addOne(); // returns [1]
addOne(); // returns [1] again, this is crucial here    

Теперь давайте сравним его с Python:

def addOne(ary=[]):
    ary.append(1)
    return ary

addOne([3,2]) # returns [3,2,1]
addOne([3,2]) # returns [3,2,1]

again addOne() # returns [1]
addOne() # BOOM! returns [1,1]
addOne() # and now returns [1,1,1]

Увидеть разницу? Аргумент по умолчанию всегда является одинаковым массивом Отказ В отличие от большинства языков, которые я знаю, Python не воссоздает этот объект каждый раз. Общее решение этой проблемы, к сожалению, довольно уродливая идиома:

 def addOne(ary=None):
     if ary is None:
         ary = []

     ary.append(1)
     return ary      

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

Ничто не является частным!

Хорошо, есть больше примеров, но не будем превратить эту статью в сборник. Позвольте мне просто упомянуть один последний Gogcha в этом посте – конфиденциальность … или скорее отсутствие этого. Как вы, вероятно, знаете, JavaScript не имеет явной концепции частных методов или переменных. Я имею в виду, что вы вкладываете в класс, могут быть технически доступны вне этого. Есть предложение Чтобы повернуть добавить частные методы и поля с видом необычного синтаксиса, но пока это еще не там.

Тем не менее, есть способы сделать некоторые вещи в виде частных в JS. Например, вы можете написать набор функций и переменных и Экспорт только несколько из них:

const x = 12;
const y = 10;

const pubFun = () => console.log('public');
const priFun = () => console.log('private');

export { x, pubFun };

И, конечно, вы можете использовать Teamscript, который имеет полный Java-ish (C ++ – ISH?) Набор функциональных/полевых контроля доступа .

С другой стороны, в Python по существу все доступно – нет встроенного механизма защиты. Нет Экспорт Ключевое слово – все может быть импортировано из любого модуля, все можно добраться в любом классе. Python способствует подходу «неписаное согласие», где подчеркивания используются в качестве префиксов, указывают на то, что функция или переменная не должны использоваться вне своего исходного класса или модуля:

var1 = 0; # go ahead, use it whenever you need
_var2 = 0; # should not be used outside of its class/module
__var3 = 0; # DEFINITELY should not be touched

Чтобы быть точным, Python делает немного, чтобы препятствовать использованию функций с двойным подчерком ( Подробнее об этом здесь ), но вы все равно можете использовать «частные» функции, когда вы хотите, куда бы вы ни хотели.

Больше чтчас?

Языки программирования являются очень сложными инструментами и поэтому имеют много сюрпризов. Иногда они очевидны, и мы узнаем их очень рано, и иногда требуется месяцы или даже годы, чтобы заметить поведение, которое нас удивляет. Я уверен, что Python имеет больше getchas для разработчиков Js. Если у вас есть некоторые другие примеры, скажите мне!

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

Оригинал: “https://dev.to/gregorywitek/python-gotchas-for-javascript-developers-32d9”