Пять основных вещей, которые я узнал о Python, провалив три собеседования!

Они говорят: «Бог кроется в деталях». Я явно упустил этот момент при подготовке к первым техническим собеседованиям. Хотя я потратил большую часть времени на совершенствование своих знаний структур данных и алгоритмов, я полагался на свою практику на работе, чтобы отвечать на вопросы, связанные с языком, на собеседованиях. Результат; Я провалил три интервью ужасно из-за нескольких основных понятий. Ретроспектива заставила меня понять, что я делал это все время, не зная мельчайших деталей, и, следовательно, не смог правильно ответить на них, когда их спросили.

Этот пост - первая часть из двух частей, написанных для простого объяснения некоторых очень базовых концепций Python.

1. Python - это компилируемый или интерпретируемый язык?

Ответ - "Оба". Но этот ответ, скорее всего, не даст никому работу, пока мы не объясним разницу между интерпретируемым и компилируемым языками.

Зачем нам нужен переводчик?

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

Что такое компилятор?

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

Что такое переводчик?

С другой стороны, интерпретатор переводит ваш код по одной инструкции за раз. Pro: требует времени, поскольку ошибка в строке 574 означает, что он уведомляет вас, вы исправляете ошибку, и он снова начинает перевод со строки 1. Con: После преобразования сгенерированный файл байт-кода не зависит от платформы. Независимо от того, на какой машине вы хотите запускать этот код, возьмите свою виртуальную машину с собой, и все готово, потому что сгенерированный байт-код будет запускаться на вашей PVM (виртуальной машине python), а не на фактическом физическом процессоре вашей машины. .

Теперь ответ, который может дать вам работу: python делает и то, и другое. Когда мы пишем код Python и запускаем его, компилятор генерирует файл байт-кода (с расширением .pyc или .pyo). Затем мы можем взять этот байт-код и нашу виртуальную машину python и без проблем запустить ее на любой машине. PVM в данном случае - это интерпретатор, преобразующий байт-код в машинный код.

2. Python - вызов по значению или вызов по ссылке?

И снова ответ: "Оба". Это настолько просто, что вы даже можете найти его при первом поиске в Google, но важно знать детали.

Что такое вызов по ценности?

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

Что такое "звонок по ссылке"?

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

Ссылка на вызов по объекту в Python

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

Все в Python является объектом, что означает, что значение хранится в ячейке памяти, а объявленная нами переменная является только контейнером для этого адреса памяти. Независимо от того, сколько раз мы создаем копию этого значения, все переменные по-прежнему будут указывать на одно и то же место в памяти. Следовательно, в Python нет концепции передачи копии переменной в качестве аргумента. В любом случае мы передаем ссылку (ячейку памяти) в качестве аргумента функции. Так что по сути это вызов по ссылке.

Быстрый пример, чтобы понять это, независимо от того, сколько переменных мы объявляем для хранения значения Interger 2, все они содержат один и тот же адрес памяти, потому что переменные в Python являются не чем иным, как контейнерами для адресов памяти.

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

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

Примерами изменяемых объектов в Python являются list, dict, set, байтовый массив, а i изменяемыми объектами являются int, float, комплекс, строка, кортеж, замороженный набор [примечание: неизменяемая версия набора], байты.

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

Например, когда переменная «a» ссылается на целое число, и мы пытаемся изменить ее значение, «a» начинает указывать на новую ячейку памяти, поскольку изменение значения целого числа на месте невозможно.

С другой стороны, когда «a» указывает на список, который является изменяемой структурой данных, любое изменение в списке не приведет к изменению адреса, содержащегося в «a», поскольку изменяемые структуры данных изменяются на месте.

3. В чем разница между range () и xrange ()?

range () и xrange () - встроенные функции в Python, используемые для генерации интервалов для циклов для итерации. xrange () в Python 2 был заменен на range () в Python 3.

Оба реализуются по-разному и имеют разные характеристики. Точки сравнения:

  • Тип возврата
  • объем памяти
  • Использование операции
  • Скорость

range () возвращает итерацию (список), что означает, что все значения, указанные в range (), создаются одновременно и сохраняются в памяти для удаления любого итератора. Потребление памяти в этом случае неизбежно. С другой стороны, xrange () возвращает генератор, который предоставляет элемент только по запросу, при этом память не используется.

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

Из-за того, что xrange () оценивает только объект-генератор, содержащий только значения, необходимые для ленивого вычисления, поэтому он быстрее в реализации, чем range () .

В общем, все сводится к рассматриваемому делу. Если вы ищете эффективное по времени решение, используйте range (), поскольку вам не придется каждый раз восстанавливать целочисленный объект, вместо этого в вашем распоряжении будет список для нескольких итераций. В случае, если требуется решение с эффективным использованием памяти, xrange () кажется более подходящим вариантом, поскольку ни один элемент не создается без запроса, а потребление памяти минимально.

Следующая часть этого поста будет посвящена оставшимся двум вопросам.