На логику

  • В чём разница между
func и func() 
 
### ОТВЕТ 
# Первую функцию мы не вызвали, а вторую вызвали
  • Что выведет код, почему?
a = 1
b = a
a = a + 1
print(a)
print(b) 
 
### ОТВЕТ
# 2
# 1
  • Что выведет код, почему?
a = [1]
b = a
a.append(1)
print(a)
print(b)
 
### ОТВЕТ
# [1,1]
# [1,1]
  • Что выведет код, почему?
a = 'a'
b = 'b'
b = b+b
a.append(a)
print(a)
print(b)
 
### ОТВЕТ
# 'str' object has no attribute 'append'
# bb
  • Что выведет код, почему?
a = [1,2,3]
b = a.copy()
a == b
a is b
 
### ОТВЕТ
# True
# False
 
a = [1,2,3]
b = a.copy()
b = a
a == b
b == a
 
### ОТВЕТ
# True
# True
  • Что выведет код, почему?
d1 = {1:1, 2:2, 3:3}
d2 = d1
d2[1] = 0
print(d1)
print(d2)
 
### ОТВЕТ
# {1: 0, 2: 2, 3: 3}
# {1: 0, 2: 2, 3: 3}
  • Что выведет код, почему?
a = ()
b = ()
id(a) == id(b)
 
a = []
b = []
id(a) == id(b)
 
### ОТВЕТ
# True
# False
  • Что выведет код, почему? Во втором случае мы внутри функции создали новую переменную с таким же названием и записали в неё значение
def func1(my_list):
	my_list[0] = 123
	
def func2(my_list):
	my_list = [4,5,6]
	
l1 = [1,2,3]
l2 = [1,2,3]
 
func1(l1) 
print(l1) 
func2(l2) 
print(l2) 
 
### ОТВЕТ 
# [123, 2, 3] 
# [1, 2, 3]
  • Что выведет код, почему? В первом случае у нас создаётся list внутри функции при запуске кода и мы записываем значение в него (происходит утечка памяти). Во втором мы даёт ссылку на наш list и уже заполняем значения в нём
l_arr = [1,2,3]
def func(a, L=[]):
	L.append(a)
	return L 
 
func(4)
func(5) 
tmp_l = func(6) 
print(tmp_l) 
 
func(7, l_arr) 
func(8, l_arr) 
func(9, l_arr) 
print(l_arr) 
 
### ОТВЕТ 
# [4, 5, 6] 
# [1, 2, 3, 7, 8, 9]
  • Что выведет код?
class BaseClass:
	def __init__(self):
		pass
	
	def foo(self):
		print(self.attr1)
 
class DescendantClass(BaseClass):
	def __init__(self, attr1):
		self.attr1 = attr1
 
# 1 кейс. Что выведет?
bc = BaseClass()
bc.foo()
# 2 кейс. Что выведет?
dc = DescendantClass(1)
dc.foo()
 
### ОТВЕТ
# 1 кейс ошибка. 'BaseClass' object has no attribute 'attr1'
# 2 кейс. 1

​

  • Вам дан BaseClass, напишите DescendantClass, который добавляет атрибут new_attr к аргументам __init__ , сохраняя логику BaseClass __init__.
class BaseClass:
  def __init__(self, config):
    self.config = config
    # Очень сложная логика на 100 строк		
 
class DescendantClass(BaseClass):
  def __init__(self, new_attr, config):
 
### ОТВЕТ
class BaseClass:
  def __init__(self, config):
    self.config = config
    # Очень сложная логика на 100 строк		
 
class DescendantClass(BaseClass):
  def __init__(self, new_attr, config):
    super().__init__(config)
    self.new_attr = new_attr
 
dc = DescendantClass(1,2)
print(dc.new_attr) # 1
print(dc.config) # 2

​

Итератор для чисел Фибоначчи

def fibonacci(): 
	prev, cur = 0, 1 
	while True: 
		yield prev 
		prev, cur = cur, prev + cur 
	
for i in fibonacci(): 
	print(i) 
	if i > 100: 
	  break
	
fib = fibonacci()
print(next(fib)) 
# 0 
print(next(fib)) 
# 1

Декоратор

def my_decorator(function_to_decorate):
  def wrapper(arg1, arg2):
    print("Я получил аргументы:", arg1, arg2)
    function_to_decorate(arg1, arg2)
  return wrapper
 
@my_decorator
def print_my_name(first_name, last_name):
	print("Меня зовут", first_name, last_name)
 
print_my_name("Иван", "Иванов")
 
### ОТВЕТ
# Я получил аргументы: Иван Иванов
# Меня зовут Иван Иванов