Listaértelmezés, generátorkifejezés¶

A listaértelmezés azonnal kiértékelődik és egy listát ad vissza, ami bejárható (iterálható, iterable) objektum.

A generátorkifejezés egy bejáró (iterátor, iterator), ami – mint minden bejáró – egyúttal bejárható.

A bejárható objektum olyan, amelynek elemein végigjárhatunk (pl. lista). Ha átadjuk az iter() metódusnak, egy bejáró keletkezik. A bejáró (iterator) olyan objektum, mely egy bejárható objektumon végigfut a __next__() metódussal.

In [1]:
for num in [2, 3, 5, 7]:
    print(num, end=' ')
2 3 5 7 
In [2]:
numbs = [2, 3, 5, 7]
iterator_obj = iter(numbs)
print(next(iterator_obj))
print(next(iterator_obj))
print(next(iterator_obj))
print(next(iterator_obj))
print(next(iterator_obj))
2
3
5
7
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[2], line 7
      5 print(next(iterator_obj))
      6 print(next(iterator_obj))
----> 7 print(next(iterator_obj))

StopIteration: 
In [3]:
iterator_obj = iter(numbs)
try:
    print(next(iterator_obj), end=' ')
    print(next(iterator_obj), end=' ')
    print(next(iterator_obj), end=' ')
    print(next(iterator_obj), end=' ')
    print(next(iterator_obj)) #StopIteration error
except:
    pass
2 3 5 7 

Lássuk még egyszer a különbségeket:

In [4]:
lst = [n for n in range(10000)]
gen = (n for n in range(10000))
In [5]:
print(type(lst), type(gen))
<class 'list'> <class 'generator'>
In [6]:
from sys import getsizeof
print(getsizeof(lst), getsizeof(gen))
85176 192
In [7]:
for i in lst:
    if i == 100:
        print(i)
100
In [8]:
for i in gen:
    if i == 100:
        print(i)
100
In [9]:
lst[100]
Out[9]:
100
In [10]:
gen[100]  # we can iterate through the items
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[10], line 1
----> 1 gen[100]  # we can iterate through the items

TypeError: 'generator' object is not subscriptable

A generátor nem indexelhető, és csak egyszer futhatunk végig az elemein, így – ellentétben a listával –, egymásba ágyazott ciklusoknál nem lehet mindkét bejárható objektum generátor kifejezés:

In [11]:
g1=(i for i in range(3))
g2=(j for j in range(3))
for i in g1:
    for j in g2:
        print(i,j)
0 0
0 1
0 2
In [12]:
# minden ciklusban újra kell generálni g2-t
g1=(i for i in range(3))
for i in g1:
    g2=(j for j in range(3))
    for j in g2:
        print(i,j)
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2

Feltételes relatív gyakoriság¶

Eldobunk egy piros és egy kék kockát. A rajtuk lévő számok összege legyen s. Mi a relatív gyakorisága annak, hogy a piros kockán 1-es van, feltéve, hogy a két kockán lévő számok összege s egy előre megadott, rögzített szám? Mi a relatív gyakorisága bármely másik számnak, feltéve, hogy a két kockán lévő számok összege s? Mely s összeg esetén lesz egy szám ezen feltétel melletti relatív gyakorisága közel az 1/6-hoz?

In [13]:
from random import randint
In [14]:
two = [red, _] = [randint(1,6), randint(1,6)]
two, red
Out[14]:
([3, 3], 3)
In [15]:
two = [randint(1,6), randint(1,6)]
red = two[0]
two, red
Out[15]:
([4, 2], 4)
In [16]:
s = sum(two)
In [17]:
two, s, red
Out[17]:
([4, 2], 6, 4)
In [18]:
sum2 = 7      # sum of the two numbers (2..12)
die = 1       # the number on the die we are waiting for (1..6)
count = 0     # counter of the cases with sum == <sum2>    
count_red = 0 # counter when the red die == <die>

for i in range(10000):
    two = [randint(1,6), randint(1,6)]
    red = two[0]
    s = sum(two)
    if s == sum2:
        count += 1
        if red == die:
            count_red += 1
print(count_red/count, 1/6)
0.16293155663234404 0.16666666666666666

Feltételes valószínűség¶

Eldobunk egy piros és egy kék kockát. A rajtuk lévő számok összege legyen s. Mi a valószínűsége, hogy a piros kockán lévő szám épp r, feltéve hogy az összeg az előre megadott s szám? Mely s értékekre lesz e valószínűség 1/6?

In [19]:
sum2 = 7      # sum of the two numbers 
die = 2       # the number on the die we are waiting for
count = 0     # counter of the cases with sum == <sum2>    
count_red = 0 # counter when the red die == <die>

for red in range(1, 7):
    for blue in range(1, 7):
        s = red + blue
        if s == sum2:
            count += 1
            if red == die:
                count_red += 1
print(count_red/count, 1/6)
0.16666666666666666 0.16666666666666666
In [ ]: