Ennik (tuple)

Ennik (Pythonis võtmesõna tuple), vahel ka nimetusega korteež, rida või järjend on andmetüüp, mis on väga sarnane järjendile (list). Ennik on jada Pythoni objekte.

Loomine:

Enniku loomiseks tuleb elemendid eraldada komadega ja panna ümarsulgude vahele. Elementide arv pole piiratud ja elemendid võivad olla erinevat andmetüüpi - näiteks ujukomaarv (float), täisarv (int), järjend (list), sõne (str), jne Programmis kasutatakse enniku kirjeldamiseks ümarsulge “(...,...)” (erinevalt listist, kus oli kandilised sulud “[...,...]”).Kuigi aga nende indekseerimiseks kasutatakse siiski nurksulge.

Tegelikult saaksime alati ennikute asemel kasutada ka järjendeid, aga heaks tavaks on kasutada järjendeid vaid neil juhtudel, kus kogumi elemendid on kõik ühte tüüpi. (nt [1,2,3..] või [“hello”, “world!”]...)

Ennikuid võiks eelistada siis, kui meil on mingi kindel komplekt elemente, mida me tahame koos käsitleda, kusjuures iga element võib olla erinevat tüüpi.

tup0 = ()  # empty tuple
tup1 = (1,)  # need to use a comma with one element
tup2 = (1, 2)
tup3 = ("hello", 123, "abc")  # different types
tup4 = ("wasd", tup3, 777.2)  # -> ('wasd', ('hello', 123, 'abc'), 777.2)

# parentheses can be omitted, but it's safer to use them
tup5 = 1,  # use of comma!
tup6 = 1, 3, 5

# tuple of list
tup7 = tuple([4])  # -> (4,)
tup8 = tuple(["Boeing", 737, "Cessna", 210])  # -> ("Boeing", 737, "Cessna", 210)

# list of tuple
list1 = list(tup7)  # -> [4]
list2 = list(tup8)  # -> ["Boeing", 737, "Cessna", 210]
empty = ()
singleton = 'hello',    # <-- note trailing comma
print(len(empty))  #0
print(len(singleton))  #1
print(singleton)  #('hello',)

Võrdlus järjendiga:

Ennik erineb järjendist (list) peamiselt selle poolest, et see on muutumatu (immutable) ja puuduvad paljud meetodid, mis on olemas järjendil. Enniku kasutamine aitab muuta koodi selgemaks ja arusaadavamaks garanteerides selle, et andmed seal on konstantsed ja neid ei saa muuta.

Ennikud on pisut kiiremad kui järjendid. Kui kasutad konstantseid väärtuseid, siis eelista võimalusel ennikut järjendile.

Ennikule ei saa lisada elemente. Puuduvad append ja extend meetodid. Ennikult ei saa eemaldada elemente. Puuduvad remove ja pop meetodid.

aList = [4, 2]
aList[0] = 1
print(aList)  # -> [1, 2]

aTuple = (4, 2)
aTuple[0] = 1  # -> TypeError: 'tuple' object does not support item assignment

Ennikut saab kasutada sõnastiku (dictionary) võtmena (key), kuid järjendit ei saa, sest järjend on muutuv (mutable).

dict1 = {(2, 3): "abc"}  # Ennik sobib sõnastiku võtmeks
dict2 = {[2, 3]: "abc"}  # TypeError: unhashable type: 'list'

Nii loendit kui ka ennikut saab määrata vastavalt omanimelise funktsiooniga.

arvud = tuple(range(10))
tekst = tuple('python')
print(arvud)                        #(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
print(tekst)                        #('p', 'y', 't', 'h', 'o', 'n')

Juurdepääs elementidele ja operatsioonid ennikutel:

Ennikus olevaid elemente saab kätte indeksi järgi [] operaatoriga. Indekseerimine algab 0-st.

a_tuple = ("January", "February", "March")
# index        0          1          2
print(a_tuple[0])  # -> January
print(a_tuple[2])  # -> March

# tuple of string works like a list by splitting the contents
b_tuple = tuple("Technology")  # -> ('T', 'e', 'c', 'h', 'n', 'o', 'l', 'o', 'g', 'y')
print(b_tuple[0])  # -> T
print(b_tuple[4])  # -> n

# index has to be of type int and int range 0 to len(b_tuple) - 1, last element is at index len(b_tuple) - 1
# print(a_tuple[10])  # -> IndexError: tuple index out of range

Python lubab kasutada negatiivset indekseerimist oma järjendites sealhulgas ka ennikutes. -1 viitab viimasele elemendile, -2 eelviimasele jne.

c_tuple = ("n", "i", "c", "e")
print(c_tuple[-1])  # -> e
print(c_tuple[-2])  # -> c

Tükeldamise abil saab ligi kindlale vahemikule ennikus sarnaselt paljudele teistele andmetüüpidele. Tükeldamine toimub kasutades koolonit. Tükeldamise tähistus: [start:stop:step]

  • [start] indeks, kust alustada tükeldamist, selle ärajätmisel eeldab Python, et tükeldamine algab algusest
  • [stop] elemendi indeks, kus peatuda, seda elementi ei arvata vahemikku
  • [step] sammu suurus itereerimisel, vaikimisi on see 1, -1 itereerib elemendid tagurpidi
c_tuple = ("a", "b", "c", "d")

# range of elements between index 0 and index 2, element at index 2 is excluded
print(c_tuple[0:2])  # -> ('a', 'b')

# [start] can be omitted
print(c_tuple[:2])  # -> ('a', 'b')

print(c_tuple[2:4])  # -> ('c', 'd')

# [stop] can be omitted
print(c_tuple[2:])  # -> ('c', 'd')

# slicing from start to end, easy way to make a copy
print(c_tuple[:])  # -> ("a", "b", "c", "d")

# by choosing [step] to be -1, we get the reverse of original
print(c_tuple[::-1])  # -> ('d', 'c', 'b', 'a')

Enniku puhul saab kasutada in operaatorit, et kontrollida elemendi olemasolu ennikus.

tup = (123, "hello", 999)
b = "hello" in tup
print(b)  # -> True

Enniku muutmine:

Kuna ennik on erinevalt järjendist muutumatu, siis pole võimalik enniku elemente peale esialgset määramist muuta. Erandiks on olukord, kus ennik sisaldab järjendit, mis võib muutuda.

a_list = [0, 1, 2]
x_tuple = (3, a_list, 4)
a_list.append(9)
print(x_tuple)  # -> (3, [0, 1, 2, 9], 4)

Sama muutujat saab asendada, esialgne: y_tuple = (5, 2) asendamine: y_tuple = (3, 3)

Kuna elemente ei saa ennikus eemaldada, siis on enniku kustutamiseks olemas võtmesõna del.

my_tuple = (1, 2)
del my_tuple  # deleting
print(my_tuple)  # -> NameError: name 'my_tuple' is not defined

Ennikute uuendamiseks võib osaliselt kasutada vanu väärtusi.

tup0 = ("a", "b")
tup1 = (1,)
tup3 = tup0 + tup1
print(tup3)  # -> ('a', 'b', 1)
tup4 = tup3 * 3
print(tup4)  # -> ('a', 'b', 1, 'a', 'b', 1, 'a', 'b', 1)

Meetodid:

count(x) - Tagastab arvu, mis näitab, mitu elementi on võrdsed x-ga.

index(x) - Tagastab esimese elemendi indeksi, mis on võrdne x-ga.

print(tuple("Tallinn University of Technology").count("l"))  # -> 3
print(tuple("Tallinn University of Technology").index("y"))  # -> 17

Ennikutega kasutatakse tihti mitmeid Pythoni sisse ehitatud funktsioone. Nende kohta saab lugeda siit: https://docs.python.org/3/library/functions.html.

Kasutamine:

Pythonis kasutatakse tihti ennikut muutujate pakkimiseks:

fruits = "apple", "orange", "pear"  # tuple packing
f0, f1, f2 = fruits  # tuple unpacking
# f0 -> apple
# f1 -> orange
# f2 -> pear

cities = "London", "Ottawa", "Bristol", "New York", "Oslo"
uk, ca, *other_cities, nor = cities  # the * operator just before a variable takes logically rest of the values
# other_cities -> ['Bristol', 'New York']

uk2, *other_cities2 = cities
# other_cities2 -> ['Ottawa', 'Bristol', 'New York', 'Oslo']

Ennikut on hea kasutada, kui on vaja, et funktsioon tagastaks mitu väärtust.

def hello():
    return "Hi", "Tom"  # looks like several values are returned, actually it's just a tuple with without parentheses

print(type(hello()))  # <class 'tuple'>

h = hello()[0]
t = hello()[1]
# one liner with tuple unpacking -> h, t = hello()
# h = "Hi", t = "Tom"