+ All Categories
Home > Documents > Řetězce, seznamy, ntice - IB111 Základy programování · INDEXOVÁNÍ Indexováníodnuly •...

Řetězce, seznamy, ntice - IB111 Základy programování · INDEXOVÁNÍ Indexováníodnuly •...

Date post: 17-Apr-2020
Category:
Upload: others
View: 5 times
Download: 0 times
Share this document with a friend
39
ŘETĚZCE, SEZNAMY, NTICE IB111 ZÁKLADY PROGRAMOVÁNÍ Nikola Beneš 10. října 2019
Transcript
  • ŘETĚZCE, SEZNAMY, NTICEIB111 ZÁKLADY PROGRAMOVÁNÍ

    Nikola Beneš10. října 2019

  • ŘETĚZCE

  • ŘETĚZCE – SYNTAX (V PYTHONU)

    • uvozovky: "Toto je text."• alternativně apostrofy: 'Toto je taky text.'• víceřádkové řetězce:

    text = """Toto je text,který pokračuje na dalším řádku.A potom ještě na jednom."""

    • speciální symboly – uvozené zpětným lomítkem \• konec řádku \n• tabulátor \t• uvozovka \", apostrof \'• zpětné lomítko \\• … a různé jiné

    print("\N{grinning face}")

    1

    text = """Toto je text,který pokračuje na dalším řádku.A potom ještě na jednom."""

    print(text)

    print("\N{grinning face}")

  • ŘETĚZCE – ZÁKLADNÍ OPERACE

    • zřetězení: "ahoj, " + "lidi"• „násobení“: "kolo" * 3 (specialita Pythonu)• porovnávání• typování konverze čísla na řetězec: str(3.14)• přiřazení do proměnné: text = "Dnes je pěkně."• délka textu (počet znaků): len(text)• indexování (výběr konkrétního znaku): text[0], text[2]• indexování od konce: text[-1]• pořadové číslo znaku (v Unicode): ord("b")• znak pro zadané pořadové číslo: chr(99)

    2

  • INDEXOVÁNÍ

    Indexování od nuly

    • první znak řetězce je text[0]• částečně historicko-technické důvody• ale i dobré „matematické“ důvody• souvisí s oblibou polouzavřených intervalů ⟨𝑜𝑑, 𝑑𝑜)

    Pro zajímavost:

    • https://en.wikipedia.org/wiki/Zero-based_numbering• https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html

    • https://softwareengineering.stackexchange.com/questions/110804/why-are-zero-based-arrays-the-norm

    3

    https://en.wikipedia.org/wiki/Zero-based_numberinghttps://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.htmlhttps://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.htmlhttps://softwareengineering.stackexchange.com/questions/110804/why-are-zero-based-arrays-the-normhttps://softwareengineering.stackexchange.com/questions/110804/why-are-zero-based-arrays-the-norm

  • POKROČILEJŠÍ INDEXOVÁNÍ

    (specifické pro Python)

    text[0:3] # první 3 znakytext[:3] # --- totéž ---text[3:] # od 4. znaku do koncetext[1:8:2] # od 2. znaku po 7., jen každý druhý znaktext[::3] # od začátku do konce, každý třetí

    • všimněte si podobnosti s range() – není náhodná

    4

  • REPREZENTACE ŘETĚZCŮ V POČÍTAČI

    Jak jsou znaky reprezentovány v počítači?

    • ASCII, ISO8859-2, Windows-1250, Unicode (UTF-8, UTF-16, UTF-32),…

    • Python umí pracovat s různými kódováními• zdrojový soubor programu je v UTF-8 (dá se změnit) (Python 3)• interní reprezentace řetězců v Pythonu:

    • složitější (PEP-393), ale pokrývá celý Unicode

    • pro účely tohoto předmětu:• ord, chr – převod znaků na čísla a zpět• znaky anglické abecedy mají přiřazena po sobě jdoucí čísla

    for i in range(26):print(chr(ord('A') + i))

    5

    for i in range(26): print(chr(ord('A') + i))

  • MODIFIKACE ŘETĚZCŮ

    • řetězce v Pythonu jsou neměnné (immutable)• rozdíl proti řetězcům v některých jiných jazycích• rozdíl proti seznamům v Pythonu

    • místo změny znaku musíme vytvořit nový řetězec

    text = "holinky"# text[2] = "d" # error!text = text[:2] + "d" + text[3:]

    6

    text = "holinky"# text[2] = "d" # error!text = text[:2] + "d" + text[3:]

    print(text)

  • ŘETĚZCE – DALŠÍ OPERACE

    text = "hello, world!"print(text.upper())print(text.lower())print(text.capitalize())print(text.rjust(30))print(">" + text.center(30) + "" + text.center(30) + "

  • ŘETĚZCE – FORMÁTOVÁNÍ

    Vkládání čísel (a jiných hodnot) do řetězců

    • starý způsob:"Jmenuji se %s a je mi %d let." % ("Metuzalém", 900)

    • nový způsob (od Pythonu 3.1): metoda format()• nejnovější způsob (od Pythonu 3.6): tzv. f-strings

    print("Dnes je {}. {}. ({})".format(10, "října", "čtvrtek"))

    print("Je právě {:d}.{:02d}".format(17, 7))print("X{:10}X".format("text"))print("X{:^10}X".format("text"))print("{:.2f}".format(math.pi))

    • format toho umí spoustu: https://pyformat.info/8

    https://pyformat.info/

    import math

    print("Dnes je {}. {}. ({})" .format(10, "října", "čtvrtek"))print("Je právě {:d}.{:02d}".format(17, 7))print("X{:10}X".format("text"))print("X{:^10}X".format("text"))print("{:.2f}".format(math.pi))

    print(f"{math.pi:.2f}")

  • PŘÍKLAD – CAESAROVA ŠIFRA

    • vstup: text, posun• výstup: zašifrovaný text

    def caesar_cipher(text, shift):result = ""text = text.upper()for char in text:

    if char.isalpha():code = (ord(char) - ord('A') + shift) % 26result += chr(code + ord('A'))

    else:result += char

    return result

    • jak dešifrovat? jak dešifrovat, když neznáme posun?

    LBH YBFG GUR TNZR 9

    def caesar_cipher(text, shift): result = "" text = text.upper() for char in text: if char.isalpha(): code = (ord(char) - ord('A') + shift) % 26 result += chr(code + ord('A')) else: result += char return result

    print(caesar_cipher("This is a very secret message.", 3))

  • PŘÍKLAD – STRATEGIE PRO KÁMEN, NŮŽKY, PAPÍR

    def strategy_uniform_1():choice = random.randint(1, 3)if choice == 1:

    return "R"if choice == 2:

    return "S"return "P"

    def strategy_uniform_2():return "RSP"[random.randint(0, 2)]

    def strategy_uniform_3():return random.choice("RSP")

    10

    import random

    def strategy_uniform_1(): choice = random.randint(1, 3) if choice == 1: return "R" if choice == 2: return "S" return "P"

    def strategy_uniform_2(): return "RSP"[random.randint(0, 2)]

    def strategy_uniform_3(): return random.choice("RSP")

  • SEZNAMY, NTICE

  • MOTIVACE PRO SEZNAMY

    • chceme zpracovávat větší množství položek• nechceme psát opakovaně stejný kód (DRY)• nemusíme předem znát počet položek

    Příklady

    • simulace preferencí politických stran (minule)• frekvence písmen v textu• seřazení studentů podle počtu bodů• reprezentace herního plánu (piškvorky, šachy)• …

    11

  • PŘÍKLAD: FREKVENCE PÍSMEN (NEVHODNÉ ŘEŠENÍ)

    def frequency_analysis(text):text = text.upper()freqA = 0freqB = 0freqC = 0for letter in text:

    if letter == "A":freqA += 1

    elif letter == "B":freqB += 1

    elif letter == "C":freqC += 1

    print("A:", freqA)print("B:", freqB)print("C:", freqC)

    12

    def frequency_analysis(text): text = text.upper() freqA = 0 freqB = 0 freqC = 0 for letter in text: if letter == "A": freqA += 1 elif letter == "B": freqB += 1 elif letter == "C": freqC += 1 print("A:", freqA) print("B:", freqB) print("C:", freqC)

    jabberwocky = """Jabberwocky

    'Twas brillig, and the slithy tovesDid gyre and gimble in the wabe;All mimsy were the borogoves,And the mome raths outgrabe."""

    frequency_analysis(jabberwocky)

  • SEZNAMY V PYTHONU

    0 1 2 3 4

    • libovolný počet položek v pořadí za sebou• indexováno od nuly (jako řetězce)• běžně dostupné v jiných jazycích

    • pole (array) – pevná délka, všechny položky stejného typu• dynamická pole, seznamy, …

    • seznamy v Pythonu – obecnější než pole• umí měnit velikost• smí obsahovat položky různých typů• (ale práce se seznamy je pomalejší)

    • pole v Pythonu (knihovna NumPy; nad rámec předmětu)

    13

  • VYTVOŘENÍ SEZNAMU

    • výčtem prvků

    s = []s = [3, 1, 4, 1, 5]s = ["ABC", 3.14, -7]s = [[1, 2], [3, 4]]s = ["pes", "kočka", 0.01, ["velbloud", -13], []]

    • tzv. list comprehension (intenzionální zápis seznamu)

    s = [2 * x for x in range(10)]s = [x ** 2 for x in range(1, 10) if x % 2 == 0]s = [3 * x for x in [5, 17, 23, 40]]s = [[a, b, c] for a in range(1, 10)

    for b in range(1, 10)for c in range(1, 10)if a ** 2 + b ** 2 == c ** 2] 14

    s = []s = [3, 1, 4, 1, 5]s = ["ABC", 3.14, -7]s = [[1, 2], [3, 4]]s = ["pes", "kočka", 0.01, ["velbloud", -13], []]

    s = [2 * x for x in range(10)]s = [x ** 2 for x in range(1, 10) if x % 2 == 0]s = [3 * x for x in [5, 17, 23, 40]]s = [[a, b, c] for a in range(1, 10) for b in range(1, 10) for c in range(1, 10) if a ** 2 + b ** 2 == c ** 2]

    print(s)

  • OPERACE SE SEZNAMY

    len(s) # délka seznamus.append(17) # přidání prvku na konec seznamus.pop() # odebrání prvku z konce seznamus + t # zřetězení seznamůs * 3 # opakování (pozor, může být zákeřné)

    s[0] # přístup k prvnímu prvkus[2] = "ABC" # seznamy můžeme modifikovat!s[-1] # indexování od konces[1:4] # kopie části seznamus[1:5:2] # podobně jako u řetězcůs[:] # kopie celého seznamu (k čemu to je?)

    list(x) # konverze na seznam (uvidíme později)

    15

  • PROCHÁZENÍ SEZNAMU

    • mám seznam my_list a chci vypsat všechny jeho prvky, jak?

    • ne úplně vhodné řešení:

    for i in range(len(my_list)):print(my_list[i])

    • lepší řešení:

    for element in my_list:print(element)

    • podobnou notaci má většina moderních jazyků

    • range(...) je něco jako seznam• (kvůli efektivitě to není seznam, ale tzv. generátor)• seznam můžeme vyrobit konvertováním list(range(...))

    16

  • ODBOČKA – PROMĚNNÉ V PYTHONU

    Proměnné v různých programovacích jazycích

    • pojmenované místo v paměti• odkaz na místo v paměti (Python)• kombinace obou přístupů

    Přiřazení v různých jazycích

    • proměnné ve stylu C (Pascal): změna obsahu paměti• proměnné ve stylu Pythonu: změna (přesměrování) odkazu najiné místo v paměti

    Poznámka: U neměnných (immutable) typů (čísla, řetězce)nepozorujeme žádný rozdíl.

    17

  • ODBOČKA – PROMĚNNÉ V PYTHONU

    Ilustrace přiřazení

    Jazyk CProměnné jako místa v paměti

    int a, b;a = 1;

    a = 2;

    b = a;

    a 1

    b

    a 2

    b

    a 2

    b 2

    Jazyk PythonProměnné jako odkazy

    a = 1

    a = 2

    b = a

    a 1

    a 1

    2

    a

    b

    1

    2

    18

  • SEZNAMY A PROMĚNNÉ V PYTHONU

    s = [1, 2, 3]t = ss.append(4)print(t)

    Co bude výstupem? [1, 2, 3, 4]

    • proč?• protože proměnné v Pythonu jsou odkazy• http://www.pythontutor.com

    Už víme, k čemu je dobré s[:]?

    • pokud potřebujeme vytvořit novou kopii seznamu(nezávislou na původním seznamu)

    19

    http://www.pythontutor.com

    s = [1, 2, 3]t = ss.append(4)print(t)

  • SEZNAMY A VOLÁNÍ FUNKCÍ V PYTHONU

    def fun(x):x = 17

    y = 10fun(y)print(y)

    Co bude výstupem? 10

    • vypadá to, že funkce v Pythonu nemění hodnotu parametru(čísla jsou v Pythonu neměnná)

    20

    def fun(x): x = 17

    y = 10fun(y)print(y)

  • SEZNAMY A VOLÁNÍ FUNKCÍ V PYTHONU

    def fun(s):s.append(17)

    t = [1, 2]fun(t)print(t)

    Co bude výstupem? [1, 2, 17]

    • vypadá to, že funkce v Pythonu mění hodnotu parametru(seznamy jsou v Pythonu měnitelné)

    21

    def fun(s): s.append(17)

    t = [1, 2]fun(t)print(t)

  • SEZNAMY A VOLÁNÍ FUNKCÍ V PYTHONU

    def fun(s):s.append(17)s = [4, 5]s.append(19)

    t = [1, 2]fun(t)print(t)

    Co bude výstupem? [1, 2, 17]

    • proč?• přiřazení je změna odkazu• po provedení s = [4, 5] už s neukazuje na původní seznam• http://www.pythontutor.com

    (vrátíme se k tomu v některé z dalších přednášek) 22

    http://www.pythontutor.com

    def fun(s): s.append(17) s = [4, 5] s.append(19)

    t = [1, 2]fun(t)print(t)

  • SEZNAMY A PARAMETRY S IMPLICITNÍ HODNOTOU

    • poněkud nepříjemná vlastnost Pythonu

    def fun(my_list=[]):my_list.append(1)print(my_list)

    • zkuste si opakovaně zavolat fun()

    • pointa: nepoužívejte parametry s implicitními hodnotami, pokudjsou měnitelných typů (zatím známe jen seznamy)

    23

    def fun(my_list=[]): my_list.append(1) print(my_list)

    fun()fun()fun([1, 2, 3])fun()

    # try running pylint on this file

  • VZTAH ŘETĚZCŮ A SEZNAMŮ

    • split – vytvoření seznamu z řetězce

    vowels = "a, e, i, o, u"vowel_list = vowels.split(", ")

    message = ".-|....|---|.---"letters = message.split("|")

    • join – vytvoření řetězce ze seznamu

    data = ["liberté", "égalité", "fraternité"]result = ", ".join(data)

    24

    data = ["liberté", "égalité", "fraternité"]result = ", ".join(data)

    print(result)

    vowels = "a, e, i, o, u"vowel_list = vowels.split(", ")

    message = ".-|....|---|.---"letters = message.split("|")

    print(vowel_list)print(letters)

  • NTICE (TUPLES)

    • neměnná varianta seznamů• podobně jako řetězce

    • v Pythonu fungují jako seznamy, ale nedají se měnit• zápis: kulaté závorky místo hranatých

    • v jistých situacích se kulaté závorky smí vynechat

    s = (1, "A", 3)print(s[0]) # OK# s[0] = "B" # error

    • typická použití – jednoduchá strukturovaná data• souřadnice (x, y)• barva pixelu (red, green, blue)• vracení více hodnot z funkce, …

    • ntice velikosti 1: (x,)

    25

    s = (1, "A", 3)print(s[0]) # OK# s[0] = "B" # error

    data = ("Rick Sanchez", "C317", "Earth")name, dimension, planet = data

    a = 10b = 17# we could also write: a, b = 10, 17

    a, b = b, a # the same as: (a, b) = (b, a)

    print(a, b)

    def minmax(a, b): return min(a, b), max(a, b)

    x, y = minmax(9.7, 3.14)print(x, y)

    quot, rem = divmod(17, 5) # standard Python functionprint(quot, rem)

  • TYPICKÁ POUŽITÍ NTIC

    • rozbalení ntice (funguje i se seznamy)

    data = ("Rick Sanchez", "C317", "Earth")name, dimension, planet = data

    • prohození hodnot proměnných (swap)

    a, b = b, a # the same as: (a, b) = (b, a)

    • vracení více hodnot z funkce

    def minmax(a, b):return min(a, b), max(a, b)

    x, y = minmax(9.7, 3.14)

    quot, rem = divmod(17, 5) # standard Python function26

    s = (1, "A", 3)print(s[0]) # OK# s[0] = "B" # error

    data = ("Rick Sanchez", "C317", "Earth")name, dimension, planet = data

    a = 10b = 17# we could also write: a, b = 10, 17

    a, b = b, a # the same as: (a, b) = (b, a)

    print(a, b)

    def minmax(a, b): return min(a, b), max(a, b)

    x, y = minmax(9.7, 3.14)print(x, y)

    quot, rem = divmod(17, 5) # standard Python functionprint(quot, rem)

  • ŘEŠENÉ PŘÍKLADY

  • VÝPOČET PRŮMĚRU

    def average1(data):total = 0for i in range(len(data)):

    total += data[i]return total / len(data)

    def average2(data):total = 0for element in data:

    total += elementreturn total / len(data)

    def average3(data):return sum(data) / len(data)

    • pointa? není nutné vynalézat kolo(i když se samozřejmě hodí vědět, co se vlastně děje) 27

    def average1(data): total = 0 for i in range(len(data)): total += data[i] return total / len(data)

    def average2(data): total = 0 for element in data: total += element return total / len(data)

    def average3(data): return sum(data) / len(data)

    s = [29, 998, 559, 671, 349]

    print(average1(s))print(average2(s))print(average3(s))

  • DĚLITELÉ ČÍSLA

    def divisors(num):result = []for divisor in range(1, num + 1):

    if num % divisor == 0:result.append(divisor)

    return result

    • dalo by se nějak vylepšit?• počítat jen do num // 2 (a přidat num na konec)• využít toho, že divisor a num // divisor jsou oba dělitelé• menší z těchto dvou dělitelů je ≤ odmocnině z num(zkuste si do příště naprogramovat)

    • pro zajímavost (použití intenzionálních seznamů):

    def divisors2(num):return [divisor for divisor in range(1, num + 1)

    if num % divisor == 0] 28

    def divisors(num): result = [] for divisor in range(1, num + 1): if num % divisor == 0: result.append(divisor) return result

    def divisors2(num): return [divisor for divisor in range(1, num + 1) if num % divisor == 0]

    print(divisors(72525))

  • PŘÍKLAD: SIMULACE PŘEDVOLEBNÍHO PRŮZKUMU

    def survey(size, preferences):parties = len(preferences)count = [0] * partiesfor i in range(size):

    r = random.randint(1, 100)threshold = 0for p in range(parties):

    threshold += preferences[p]if r

  • PŘÍKLAD: FREKVENČNÍ ANALÝZA

    def frequency_analysis(text):text = text.upper()freq = [0 for i in range(26)]for letter in text:

    if "A"

  • PŘÍKLAD: PŘEVOD DO MORSEOVKY

    MORSE = (".-", "-...", "-.-.", "-..") # etc.

    def to_morse(text):text = text.upper()result = ""for letter in text:

    if "A"

  • PŘÍKLAD: PRVOČÍSLA – ERATOSTHENOVO SÍTO

    def sieve(limit):result = []is_prime = [True] * limitfor p in range(2, limit):

    if is_prime[p]:result.append(p)for mult in range(p * p, limit, p):

    is_prime[mult] = Falsereturn result

    sum_primes = sum(sieve(1000000))

    print("Součet všech prvočísel menších než milion je {}.".format(sum_primes))

    32

    def sieve(limit): result = [] is_prime = [True] * limit for p in range(2, limit): if is_prime[p]: result.append(p) for mult in range(p * p, limit, p): is_prime[mult] = False return result

    sum_primes = sum(sieve(1000000))

    print("Součet všech prvočísel menších než milion je {}." .format(sum_primes))

  • PŘÍKLAD: VÝŠKOVÝ PROFIL

    33

  • PŘÍKLAD: VÝŠKOVÝ PROFIL

    def height_profile(heights):for level in range(max(heights), 0, -1):

    for height in heights:if height >= level:

    print("# ", end="")else:

    print(" ", end="")print()

    34

    def height_profile(heights): for level in range(max(heights), 0, -1): for height in heights: if height >= level: print("# ", end="") else: print(" ", end="") print()

    def elevation(heights): ascent, descent = 0, 0 for i in range(len(heights) - 1): diff = heights[i + 1] - heights[i] if diff > 0: ascent += diff else: descent += -diff print("Total ascent:", ascent) print("Total descent:", descent)

    trip = [10, 9, 7, 5, 3, 2, 2, 3, 4, 6, 7, 8, 11, 10, 8, 7, 6, 5, 5, 6]height_profile(trip)elevation(trip)

  • PŘÍKLAD: VÝŠKOVÝ PROFIL

    def elevation(heights):ascent, descent = 0, 0for i in range(len(heights) - 1):

    diff = heights[i + 1] - heights[i]if diff > 0:

    ascent += diffelse:

    descent += -diffprint("Total ascent:", ascent)print("Total descent:", descent)

    35

    def height_profile(heights): for level in range(max(heights), 0, -1): for height in heights: if height >= level: print("# ", end="") else: print(" ", end="") print()

    def elevation(heights): ascent, descent = 0, 0 for i in range(len(heights) - 1): diff = heights[i + 1] - heights[i] if diff > 0: ascent += diff else: descent += -diff print("Total ascent:", ascent) print("Total descent:", descent)

    trip = [10, 9, 7, 5, 3, 2, 2, 3, 4, 6, 7, 8, 11, 10, 8, 7, 6, 5, 5, 6]height_profile(trip)elevation(trip)

    ŘetězceSeznamy, nticeŘešené příklady


Recommended