#%% namedtuple: import
from collections import namedtuple


#%% Definice:

Person = namedtuple('Person', ['first_name', 'last_name'])
speaker = Person('Jan', 'Smitka')
print(f'Speaker: {speaker}')
print(f'first_name: {speaker.first_name}')
print(f'last_name: {speaker.last_name}')


#%% Pořád jde o tuple:
print(f'first_name: {speaker[0]}')
print(f'last_name: {speaker[1]}')
print(f'_fields: {speaker._fields}')


#%% A nelze jej upravit:
speaker.first_name = ''


#%% Nová možnost definice od Pythonu 3.6:
from typing import NamedTuple


class Person(NamedTuple):
    first_name: str
    last_name: str

    def get_full_name(self):
        return f'{self.first_name} {self.last_name}'


speaker = Person('Jan', 'Smitka')
print(f'person = {speaker.get_full_name()}')


#%% ChainMap: import
from collections import ChainMap


#%% Typické použití - konfigurace na různých úrovních:
global_config = {
    'max_connections': 10,
    'user_agent': 'Mozilla/5.0 (Sirius Cybernetics Robot; en-gb) Python/3.7 (CPython) Genuine People Personality',
    'proxy': None,
}

user_config = {
    'max_connections': 20,
    'username': 'panda',
}

project_config = {
    'user_agent': 'Mozilla/5.0',
    'bind_host': '::1'
}

config = ChainMap(project_config, user_config, global_config)
for item, value in config.items():
    print(f'{item} = {value}')


#%% Konverze na dict
print(f'config = {dict(config)}')


#%% Úpravy se projeví v prvním slovníku:
config['max_connections'] = 60
config['new_key'] = 'Python'
print(f'project_config = {project_config}')
print(f'user_config = {user_config}')
print(f'global_config = {global_config}')


#%% Derivace:
new_config = config.new_child()
new_config['new_key'] = 'Python/3.7'
print(f'new_config = {new_config}')

#%% Rodičovské slovníky:
parents = new_config.parents
print(f'parents = {parents}')


#%% OrderedDict
from collections import OrderedDict

ordered_dict = OrderedDict()
for i in range(10):
    ordered_dict[i] = f'Value {i}'

for key, value in ordered_dict.items():
    print(f'{key} = {value}')


#%% Od Pythonu 3.6 jsou všechny slovníky seřazené:
regular_dict = {}

for i in range(10):
    regular_dict[i] = f'Value {i}'

for key, value in regular_dict.items():
    print(f'{key} = {value}')


#%% defaultdict: import
from collections import defaultdict

#%%
dd = defaultdict(lambda: 42)
print(f'dd[15] = {dd[15]}')


#%% defaultdict: základní použití:
frequencies = defaultdict(int)
for word in ('python', '3.7', 'is', 'the', 'best', 'python', 'up', 'to', 'date',
             'it', 'is', 'the', 'best'):
    frequencies[word] += 1
print(f'frequencies = {frequencies}')


#%% defaultdict: další možnosti definice továrny:
frequencies = defaultdict(lambda: 10)
for word in ('python', '3.7', 'is', 'the', 'best', 'python', 'up', 'to', 'date',
             'it', 'is', 'the', 'best'):
    frequencies[word] += 1
print(f'frequencies = {frequencies}')


#%% defaultdict: další možnosti definice továrny:
buckets = defaultdict(list)
for word in ('python', '3.7', 'is', 'the', 'best', 'python', 'up', 'to', 'date',
             'it', 'is', 'the', 'best'):
    buckets[word[:1]].append(word)
print(f'buckets = {buckets}')
