<jupyter_start><jupyter_text>1<jupyter_code>class MyList:
    def __init__(self, collection=[]):
        self._collection = collection
        
    def __str__(self):
        return str(self._collection)
    
    def __len__(self):
        return len(self._collection)
        
    def insert(self, idx, value):
        try: 
            self._collection.insert(idx, value)
        except Exception:
            return False
    
    def pop(self, idx=None):
        if idx is None:
            idx = -1
        try:
            return self._collection.pop(idx)
        except Exception:
            return False
        
    
my_list = MyList([1,2,3,4,5])

assert str(my_list) == '[1, 2, 3, 4, 5]'
assert len(my_list) == 5

my_list.insert(0, 42) 
assert str(my_list) == '[42, 1, 2, 3, 4, 5]'
assert my_list.pop() == 5
assert my_list.pop(0) == 42
assert my_list.pop(100500) == False<jupyter_output><empty_output><jupyter_text>2<jupyter_code>class Item:
    def __init__(self, name, price):
        self._name = name
        self._price = price
    
    def __gt__(first, second):
        return first._price > second._price
    
    def __eq__(first, second):
        return first._price == second._price
    
    def __lt__(first, second):
        return first._price < second._price
    
    def __repr__(self):
        return '-'.join([self._name, str(self._price)])

items = [Item('one', 42), Item('two', 12), Item('three', 5)]
assert str(sorted(items)) == '[three-5, two-12, one-42]'<jupyter_output><empty_output><jupyter_text>3<jupyter_code>def foo(bar):
    return bar()

class Line:
    def __init__(self, x, k=1, b=1):
        self._x = x
        self._k = k
        self._b = b
        
    def __call__(self):
        return self._k * self._x + self._b
    
line = Line(2)
assert foo(line) == 3<jupyter_output><empty_output><jupyter_text>4<jupyter_code>class Car:
    def __init__(self, brand, origin, power, car_type):
        self._brand = brand
        self._origin = origin
        self._power = power
        self._car_type = car_type
        
    def get_info(self):
        raise NotImplementedError('This method is pure virtual.')
        
class ElectroCar(Car):
    def __init__(self, brand, origin, power, car_type):
        super().__init__(brand, origin, power, car_type)
        self._engine_type = 'Electro engine'
    
    def get_info(self):
        return [v for v in \
                [self._brand, self._origin, 
                 self._power, self._car_type, 
                 self._engine_type]]
    
class GasolineCar(Car):
    pass
    
class DeiselCar(Car):
    pass


e = ElectroCar('lada', 'russia', 70, 'coupe')
e.get_info()<jupyter_output><empty_output><jupyter_text>5<jupyter_code>from functools import wraps

def to_upper(foo):
    @wraps(foo)
    def decorator(instance):
        return foo(instance).upper()
    return decorator

class MyString:
    def __init__(self, string):
        self._string = string
        
    @to_upper
    def get_string(self):
        return self._string
    
my_string = MyString('hello')
assert my_string.get_string() == 'HELLO'<jupyter_output><empty_output><jupyter_text>6<jupyter_code>class Bunch:
    def __init__(self, data):
        self._dict = dict(data)
        
    def __setattr__(self, attr, value):
        if attr == '_dict':
            super().__setattr__(attr, value)
        else:
            self._dict[attr] = value
        
    def __getattr__(self, attr):
        if attr  in ['_dict', 'get']:
            super().__getattr__(attr)
        else:
            return self._dict[attr]
        
    def __getitem__(self, key):
        return self._dict[key]
    
    def __setitem__(self, key, value):
        self._dict[key] = value

    def __str__(self):
        return str(self._dict)
    
    def __repr__(self):
        return str(self._dict)

    def get(self, attr, fallback):
        if attr in self._dict:
            return self._dict[attr]
        else: 
            return fallback
    
bunch = Bunch({1: 2})
bunch[42] = 42
bunch.x = 43
bunch.y = 100500

assert bunch[1] == 2 
assert bunch[42] == 42
assert bunch['x'] == 43 
assert bunch.x == 43 
assert bunch.y == 100500
assert bunch.get('no_such_key', False) == False<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12367740418528098, 'fraction_numerical': 0.019750764166470727, 'mean_word_length': 2.381558028616852, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '373306', 'license': 'MIT', 'n_tokens_mistral': 1484, 'n_tokens_neox': 1415, 'n_words': 325, 'path': 'lectures/11 (test #2).ipynb', 'repo_name': 'sancau/itmo', 'size': '4253'}