51 Python Interview вопрос/ответ на собеседовании для Data Scientist

Содержание страницы

Вопросы по Python для исследователей данных и разработчиков программного обеспечения

Этот вопрос звучит очень часто на каждом интервью по Python / Data Science. Обязательно запомните правильный ответ.

  • Списки изменчивы. Они могут быть изменены после создания.
  • Кортежи неизменны. Как только кортеж создан, он не может быть изменен.
  • Списки имеют порядок. Они представляют собой упорядоченную последовательность объектов одного типа. Т.е.: все имена пользователей упорядочены по дате создания,["Seth", "Ema", "Eli"]
  • Кортежи имеют структуру. Различные типы данных могут существовать в каждом индексе. Т.е.: запись базы данных в памяти (2, "Ema", "2020–04–16") # id, name, created_at

Без импорта Template класса есть 3 способа интерполировать строки.

name = 'Chris'

# 1. f strings
print(f'Hello {name}')

# 2. % operator
print('Hey %s %s' % (name, name))

# 3. format
print(
 "My name is {}".format((name))
)

3. В чем разница между «is» и «==»?

Запись is проверяет идентичность, а запись == проверяет равенство.

Рассмотрим пример. Создайте несколько списков и присвойте им имена. Обратите внимание, что b указывает на тот же объект, что и a ниже.

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

Проверьте равенство и отметьте, что все они равны.

print (a == b) 
print (a == c) 
# => True 
# => True

Но они имеют одинаковую идентичность? Нет.

print (a is b) 
print (a is c) 
# => True 
# => False

Мы можем проверить это, напечатав их идентификаторы объектов.

print(id(a))
print(id(b))
print(id(c))
#=> 4369567560
#=> 4369567560
#=> 4369567624

c has a different id than a and b.

Декоратор позволяет добавить функциональность к существующей функции, передав эту существующую функцию декоратору, который выполнит её и дополнительный код. Как бы это надстройка над существующей функцией.

Мы напишем декоратор, который будет писать лог при вызове другой функции.

Напишите функцию декоратора. Декоратор принимает функцию func, в качестве аргумента. Он также определяет функцию log_function_called, которая вызывает func()и выполняет некоторый код print(f'{func} called.'). Затем он возвращает функцию, которую он определил.

def logging(func):
  def log_function_called():
    print(f'{func} called.')
    func()
  return log_function_called

Давайте напишем другие функции, к которым мы затем добавим декоратор:

def my_name():
  print('chris')
def friends_name():
  print('naruto')

my_name()
friends_name()

#=> chris
#=> naruto

Теперь добавим декоратор к обоим функциям.

@logging
def my_name():
 print('chris')
@logging
def friends_name():
 print('naruto')

my_name()
friends_name()

#=> <function my_name at 0x10fca5a60> called.
#=> chris
#=> <function friends_name at 0x10fca5f28> called.
#=> naruto

Посмотрите, как мы можем теперь легко добавить логирование в любую функцию, которую мы пишем, просто добавив @logging над ней.

5. Объясните, как работает функция диапазона (range function)

Range генерирует список целых чисел и его можно использовать тремя способами.

Функция принимает от 1 до 3 аргументов. Рассмотрим три случая — запись с одним, двумя и тремя аргументами.

range(stop): генерирует целые числа от 0 до целого числа «stop».

for i in range(10)
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

range(start, stop): генерирует целые числа от «start» до «stop».

for i in range(2,10)
#=> [2, 3, 4, 5, 6, 7, 8, 9]

range(start, stop, step): генерирует целые числа от «start» до «stop» с интервалами «step».

for i in range(2,10,2)
#=> [2, 4, 6, 8]

Во всех случаях stop (верхняя граница) не включается в список.

6. Определите класс с именем car и с 2 свойствами, «color» и «speed». Затем создайте экземпляр и верните свойство speed

class Car :
    def __init__(self, color, speed):
        self.color = color
        self.speed = speed

car = Car('red','100mph')
car.speed

#=> '100mph'

7. В чем разница между методом класса, методом экземпляра и статическим методом в Python?

Методы экземпляра: принимают параметр self и относятся к конкретному экземпляру класса.

Статические методы: используйте декоратор @staticmethod для методов, которые не связаны с конкретными экземплярами и являются автономными (не изменяют свойств класса или экземпляра).

Методы класса: принимают параметр cls и могут изменять сам класс.

Проиллюстрируем разницу вокруг вымышленного CoffeeShop класса.

class CoffeeShop:
    specialty = 'espresso'
    
    def __init__(self, coffee_price):
        self.coffee_price = coffee_price
    
    # instance method
    def make_coffee(self):
        print(f'Making {self.specialty} for ${self.coffee_price}')
    
    # static method    
    @staticmethod
    def check_weather():
        print('Its sunny')

    # class method
    @classmethod
    def change_specialty(cls, specialty):
        cls.specialty = specialty
        print(f'Specialty changed to {specialty}')

CoffeeShop У класса есть свойство specialty, установленное значение по умолчанию 'espresso'. Каждый экземпляр CoffeeShop инициализируется со свойством coffee_price. Он также имеет 3 метода: метод экземпляра, статический метод и метод класса.

Давайте инициализируем экземпляр кофейни с coffee_price = 5. Затем вызовем метод экземпляра make_coffee.

coffee_shop = CoffeeShop('5')
coffee_shop.make_coffee()
#=> Making espresso for $5

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

coffee_shop.check_weather()
#=> Its sunny

Теперь давайте используем метод класса, чтобы изменить вид кофе, а затем вызовем метод make_coffee.

coffee_shop.change_specialty('drip coffee')
#=> Specialty changed to drip coffee

coffee_shop.make_coffee()
#=> Making drip coffee for $5

Обратите внимание, как метод make_coffee раньше изготавливал espresso, но теперь делает drip coffee!

8. В чем разница между «func» и «func()»?

Цель этого вопроса — понять, знаете ли вы, что все функции также являются объектами в Python.

def func():
    print('Im a function')
    
func
#=> function __main__.func>

func()    
#=> Im a function

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

9. Объясните, как работает функция map()

map возвращает список, составленный из возвращаемых значений, от применения функции к каждому элементу в последовательности.

def add_three(x):
    return x + 3
li = [1,2,3]
list_data = [i for i in map(add_three, li)]
print(list_data)
# [4, 5, 6]

10. Объясните, как работает функция reduce()

Эту функцию довольно сложно сразу понять, пока вы не используете её несколько раз.

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

from functools import reduce

def add_three(x,y):
    return x + y

li = [1,2,3,5]

reduce(add_three, li)
#=> 11

Возвращается значение 11, которое является суммой 1+2+3+5.

11. Объясните, как работает функция фильтра filter()

Функция filter() буквально делает то, о чем говорится в её названии: Фильтрует элементы в последовательности/списке.

Каждый элемент передается функции, которая возвращается в выведенной последовательности, если функция возвращается, True и отбрасывается, если функция возвращается False.

def add_three(x):
    if x % 2 == 0:
        return True        
    else:
        return False

li = [1,2,3,4,5,6,7,8]
new_listdata = [i for i in filter(add_three, li)]
print(new_listdata)
#=> [2, 4, 6, 8]

Обратите внимание, что все элементы, не делимые на 2, были удалены.

Неизменяемые объекты, такие как строки, числа и кортежи, вызываются по значению (т.е. в функцию передается именно значение, а не ссылка на объект). Обратите внимание, что значение name не изменилось вне функции при изменении внутри. Значение name было назначено новому блоку в памяти для переменной этой функции.

name = 'chr'
def add_chars(s):
    s += 'is'
    print(s)
    
add_chars(name)    
print(name)
#=> chris
#=> chr

Изменяемые объекты, такие как список, вызываются по ссылке. Обратите внимание, как список, определенный вне функции, был изменен внутри функции. Параметр в функции указывает на оригинальный блок в памяти, в котором сохранено значение li.

li = [1,2]
def add_element(seq):
    seq.append(3)
    print(seq)
    
add_element(li)    
print(li)
#=> [1, 2, 3]
#=> [1, 2, 3]

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

li = ['a','b','c']
print(li)
li.reverse()
print(li)
#=> ['a', 'b', 'c']
#=> ['c', 'b', 'a']

Давайте посмотрим результаты умножения строки 'cat' на 3.

'cat' * 3
#=> 'catcatcat'

Строка соединяется сама с собой 3 раза.

Давайте посмотрим результат умножения списка [1,2,3] на 2.

[1,2,3] * 2 
# => [1, 2, 3, 1, 2, 3]

Выводится список, содержащий задвоенное содержимое [1,2,3].

Self относится к экземпляру самого класса. Это то, как мы предоставляем методам доступ и возможность обновлять объект, которому они принадлежат.

Ниже передача self для __init__() дает возможность установить color для экземпляра при инициализации.

class Shirt:
    def __init__(self, color):
        self.color = color
        
s = Shirt('yellow')
s.color
#=> 'yellow'

Сумма 2х списков объединяет их:

a = [1,2]
b = [3,4,5]
c = a + b
print(c)
print(a + b)
#=> [1, 2, 3, 4, 5]
#=> [1, 2, 3, 4, 5]

18. В чем разница между мелкой и глубокой копией (shallow copy vs. deep copy)?

Мы обсудим это в контексте изменяемого объекта — списка. Для неизменных объектов, shallow copy против deep copy не столь актуально.

Мы пройдемся по 3-м сценариям.

1) Ссылка на оригинальный объект. Она указывает на новое имя, li2 указывает на то же место в памяти, на которое указывает li1. Таким образом, любое изменение, которое мы делаем в li1 также происходит в li2.

li1 = [['a'],['b'],['c']]
li2 = li1
li1.append(['d'])
print(li2)
#=> [['a'], ['b'], ['c'], ['d']]

2) Создать shallow copy оригинала. Мы можем сделать это с помощью list() конструктора или более питонического mylist.copy().
shallow copy создает новый объект, но заполняет его ссылками на оригинал. Таким образом, добавление нового объекта в исходную коллекцию li3 не распространяется на li4, а изменение одного из объектов li3 будет распространяться на li4.

li3 = [['a'],['b'],['c']]
li4 = list(li3)
li3.append([4])
print(li4)
#=> [['a'], ['b'], ['c']]
li3[0][0] = ['X']
print(li4)
#=> [[['X']], ['b'], ['c']]

3) Создать deep copy. Это сделано с copy.deepcopy(). 2 объекта теперь полностью независимы, и изменения одного из них не влияют на другой список.

import copy
li5 = [['a'],['b'],['c']]
li6 = copy.deepcopy(li5)
li5.append([4])
li5[0][0] = ['X']
print(li6)
#=> [['a'], ['b'], ['c']]

19. В чем разница между списками и массивами?

Примечание: стандартная библиотека Python имеет объект массива, но здесь я специально ссылаюсь на обычно используемый массив Numpy.

  • Списки существуют в стандартной библиотеке Python. Массивы определены Numpy.
  • Списки могут быть заполнены различными типами данных в каждом индексе. Массивы требуют однородных элементов.
  • Арифметика в списках добавляет или удаляет элементы из списка. Арифметика на массивах — это функция линейной алгебры.
  • Массивы также используют меньше памяти и обладают значительно большей функциональностью.

20. Как объединить два массива Numpy?

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

import numpy as np

a = np.array([1,2,3])
b = np.array([4,5,6])

np.concatenate((a,b))

#=> array([1, 2, 3, 4, 5, 6])

21. Назовите изменяемые и неизменяемые объекты в Python

Неизменяемые объекты — означает, что состояние не может быть изменено после создания. Примеры: int, float, bool, string и tuple.

Изменяемый объект — означает, что состояние может быть изменено после создания. Примерами являются list, dict и set.

22. Как округлить число до 3 десятичных знаков в Python?

Используйте функцию round(value, decimal_places).

a = 5.12345
round(a,3)
#=> 5.123

23. Как вывести кусок списка — slice a list?

Синтаксис slice следующий, необходимо list передать 3 аргумента, list[start:stop:step], где step (шаг) — это интервал, через который возвращаются элементы.

a = [0,1,2,3,4,5,6,7,8,9]
print(a[:2])
#=> [0, 1]

print(a[8:])
#=> [8, 9]

print(a[2:8])
#=> [2, 3, 4, 5, 6, 7]

print(a[2:8:2])
#=> [2, 4, 6]

24. Что такое pickling (маринование)?

Pickling — это метод сериализации и десериализации объектов в Python.

В приведенном ниже примере мы сериализуем и десериализуем список словарей.

import pickle
obj = [
    {'id':1, 'name':'Stuffy'},
    {'id':2, 'name': 'Fluffy'}
]
with open('file.p', 'wb') as f:
    pickle.dump(obj, f)
with open('file.p', 'rb') as f:
    loaded_obj = pickle.load(f)
print(loaded_obj)
#=> [{'id': 1, 'name': 'Stuffy'}, {'id': 2, 'name': 'Fluffy'}]

25. В чем разница между словарями (dictionaries) и JSON?

Dictionary — это тип данных Python, набор проиндексированных, но неупорядоченных ключей и значений.

JSON — это просто строка, которая следует заданному формату и предназначена для передачи данных.

26. Какие ORM вы использовали в Python?

ORM (объектно-реляционное отображение или object relational mapping) отображают модели данных (обычно в приложении) в таблицы базы данных и упрощают транзакции базы данных.

SQLAlchemy обычно используется для фреймворка Flask, а Django имеет собственный ORM.

27. Как работает any() и all()?

Any() принимает последовательность и возвращает true, если какой-либо элемент в последовательности равен true.
All() возвращает истину, только если все элементы в последовательности истинны.

a = [False, False, False]
b = [True, False, False]
c = [True, True, True]

print( any(a) )
print( any(b) )
print( any(c) )
#=> False
#=> True
#=> True

print( all(a) )
print( all(b) )
print( all(c) )
#=> False
#=> False
#=> True

28. Что быстрее для поиска элемента — словарь или список в Python?

Поиск значения в списке занимает O(n) времени, потому что весь список необходимо перебирать до тех пор, пока значение не будет найдено.

Поиск ключа в словаре занимает O(1) времени, потому что это хеш-таблица.

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

29. В чем разница между модулем и пакетом?

Модуль — это файл (или набор файлов), который можно импортировать вместе.

import sklearn

Пакет — это каталог модулей.

from sklearn import cross_validation

Таким образом, пакеты являются модулями, но не все модули являются пакетами.

30. Как увеличить и уменьшить целое число в Python?

Увеличение и уменьшение может быть сделано с += и -=.

value = 5

value += 1
print(value)
#=> 6

value -= 1
value -= 1
print(value)
#=> 4

31. Как преобразовать целое число в двоичное?

Используйте bin() функцию.

bin(5)
#=> '0b101'

32. Как удалить дубликаты элементов из списка?

Удалить дубликаты элементов из списка можно сделать путем преобразования списка в набор, а затем обратно в список.

a = [1,1,1,2,3]
a = list(set(a))
print(a)

#=> [1, 2, 3]

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

33. Как проверить, существует ли значение в списке?

Использование in.

'a' in ['a','b','c']
#=> True

'a' in [1,2,3]
#=> False

34. В чем разница между дополнением и расширением?

append добавляет значение в список, а extend добавляет в список значения из другого списка.

a = [1,2,3]
b = [1,2,3]
a.append(6)
print(a)
#=> [1, 2, 3, 6]

b.extend([4,5])
print(b)
#=> [1, 2, 3, 4, 5]

35. Как получить абсолютное значение (модуль) целого числа?

Это можно сделать с помощью abs() функции.

abs(2)
#=> 2

abs(-2)
#=> 2

36. Как объединить два списка (2 lists) в список кортежей (list of tuples)?

Вы можете использовать zip() функцию для объединения списков в список кортежей. Функция zip() не ограничена для объединения только 2 списков. zip() также можно вызвать с 3 или большим числом списков.

a = ['a','b','c']
b = [1,2,3]
[(k,v) for k,v in zip(a,b)]
#=> [('a', 1), ('b', 2), ('c', 3)]

37. Как отсортировать словарь по ключу в алфавитном порядке?

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

d = {'c':3, 'd':4, 'b':2, 'a':1}
sorted(d.items())
#=> [('a', 1), ('b', 2), ('c', 3), ('d', 4)]

38. Как класс наследуется от другого класса в Python?

В приведенном ниже примере Audi наследуется от Car. И с этим наследованием приходят методы экземпляра родительского класса (т.е. из класса Car в класс Audi).

class Car():
    def drive(self):
        print('vroom')

class Audi(Car):
    pass

audi = Audi()
audi.drive()

39. Как можно удалить все пробелы из строки?

Применяем функцию replace

s = 'A string with     white space'
s.replace(' ', '')
#=> 'Astringwithwhitespace'

40. Почему следует использовать enumerate() для выполнения итерации последовательности?

Функция enumerate() позволяет отслеживать индекс при итерации по последовательности. Это более pythonic, чем определение и увеличение целого числа, представляющего индекс.

li = ['a','b','c','d','e']

for idx,val in enumerate(li):
    print(idx, val)

#=> 0 a
#=> 1 b
#=> 2 c
#=> 3 d
#=> 4 e

41. В чем разница между pass, continue и break?

pass — значит ничего не делать. Обычно его используют, потому что Python не позволяет создавать класс, функцию или оператор if без кода внутри.
В приведенном ниже примере будет выдана ошибка без кода внутри i > 3, поэтому следует использовать pass.

a = [1,2,3,4,5]
for i in a:
    if i > 3:
        pass
    print(i)
#=> 1
#=> 2
#=> 3
#=> 4
#=> 5

continue — переводит цикл на следующий элемент и останавливает выполнение цикла для текущего элемента. Так print(i) никогда не выполнится для значений, где i < 3.

for i in a:
    if i < 3:
        continue
    print(i)
#=> 3
#=> 4
#=> 5

break — прекращает цикл и последовательность больше не повторяется. Таким образом, элементы i со значения 3 не выводятся.

for i in a:
    if i == 3:
        break
    print(i)    
#=> 1
#=> 2

42. Как перевести цикл (loop) в запись одной строки для списка (list)?

Рассмотрим цикл for (for loop) — Как было до

a = [1,2,3,4,5]
 
a2 = []
for i in a:
     a2.append(i + 1)
print(a2)
#=> [2, 3, 4, 5, 6]

Как можно преобразовать — Как стало после

a3 = [i+1 for i in a]
print(a3)
#=> [2, 3, 4, 5, 6]

Понимание списка обычно считается более pythonic, когда оно все еще читаемо.

43. Приведите пример троичного оператора (ternary operator)

Тернарный оператор (ternary operator) — это однострочный оператор if / else.
Синтаксис выглядит так ‘a if condition else b’.

x = 5
y = 10

'greater' if x > 6 else 'less'
#=> 'less'

'greater' if y > 6 else 'less'
#=> 'greater'

44. ​​Как проверить, что строка содержит только цифры?

Для этих целей Вы можете использовать функцию isnumeric()

'123a'.isnumeric()
#=> False

'123'.isnumeric()
#=> True

45. Как проверить, что строка содержит только буквы

Для этих целей Вы можете использовать функцию isalpha().

'123a'.isalpha()
#=> False

'a'.isalpha()
#=> True

46. Как проверить, что строка содержит только цифры и буквы

Для этих целей Вы можете использовать функцию isalnum().

'123abc...'.isalnum()
#=> False

'123abc'.isalnum()
#=> True

47. Как вернуть список ключей из словаря

Это может быть сделано путем передачи словарю питона list() конструктора list()

d = {'id':7, 'name':'Shiba', 'color':'brown', 'speed':'very slow'}

list(d)
#=> ['id', 'name', 'color', 'speed']

48. Как строку преобразовать в верхний и нижний регистр?

Вы можете использовать строковые методы upper() и lower() для преобразования регистра

small_word = 'potatocake'
big_word = 'FISHCAKE'

small_word.upper()
#=> 'POTATOCAKE'

big_word.lower()
#=> 'fishcake'

49. В чем разница между remove, del и pop?

remove() удаляет первое совпадающее значение

li = ['a','b','c','d']
li.remove('b')
li
#=> ['a', 'c', 'd']

del() удаляет элемент по индексу

li = ['a','b','c','d']
del li[0]
li
#=> ['b', 'c', 'd']

pop() удаляет элемент по индексу и возвращает этот элемент.

li = ['a','b','c','d']
li.pop(2)
#=> 'c'
li
#=> ['a', 'b', 'd']

50. Приведите пример словарного понимания (dictionary comprehension)

Ниже мы создадим словарь с буквами алфавита в качестве ключей и индекс в алфавите в качестве значений.

# creating a list of letters
import string
list(string.ascii_lowercase)
alphabet = list(string.ascii_lowercase)
# list comprehension
d = {val:idx for idx,val in enumerate(alphabet)} 
d
#=> {'a': 0,
#=>  'b': 1,
#=>  'c': 2,
#=> ...
#=>  'x': 23,
#=>  'y': 24,
#=>  'z': 25}

51. Как выполняется обработка исключений в Python?

Python предоставляет 3 слова для обработки исключений try, except и finally.
Синтаксис выглядит следующим образом.

try:
    # try to do this
except:
    # if try block fails then do this
finally:
    # always do this

В следующем примере блок try завершается ошибкой, потому что мы не можем складывать целые числа со строками. В except блоке val = 10 и затем finally блок печатает complete.

try:
    val = 1 + 'A'
except:
    val = 10
finally:
    print('complete')
    
print(val)
#=> complete
#=> 10

4.7 7 голоса
Рейтинг статьи
Шамаев Иван
Разработчик аналитических решений QlikView/Qlik Sense/Power BI; Python Data Scientist; Разработчик интеграционных решений на PHP, Python, JavaScript.
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x