Python - začátečník vs. iterace

Python - začátečník vs. iterace
« kdy: 29. 01. 2019, 09:01:54 »
Jako embedded vývojář si začínám hrát s Pythonem, aktuálně jsem se pustil do iterátorů, generátorů, tříd atd. Přitom jsem narazil na jednu, pro mě nevysvětlitelnou věc, týkající se funkce __next__ v třídě.

Mám kód:
Kód: [Vybrat]
class Hafani(object):
    def __init__(self):
        self.__psi = ("Kokrspanel", "Jezevcik", "Ovcak", "Kolie", "Husky")

    def __iter__(self):
        self.__index = 0
        return self

    def __next__(self):
        pes = self.__psi[self.__index]
        self.__index += 1

        if self.__index >= len(self.__psi):
            raise StopIteration
        else:
            return pes



# Example of use
stekac = Hafani()
for p in stekac:
    print(p, end = "  ")

Pokud ho spustím, vypíší se mi všechny plemena psů kromě posledního, i když bych očekával celý komplet včetně "Husky". Asi jsem slepý, ale stále nemohu přijít na to, proč to funguje zrovna takto. Poradil by někdo zkušenější?

Děkuji moc.
« Poslední změna: 29. 01. 2019, 10:55:42 od Petr Krčmář »


gll

  • ****
  • 429
    • Zobrazit profil
    • E-mail
Re:Python - Začátečník vs iterace
« Odpověď #1 kdy: 29. 01. 2019, 09:21:48 »
změňte >= na > a dejte tu podmínku na začátek.

ByCzech

  • *****
  • 1 863
    • Zobrazit profil
    • E-mail
Re:Python - Začátečník vs iterace
« Odpověď #2 kdy: 29. 01. 2019, 10:04:20 »
změňte >= na > a dejte tu podmínku na začátek.

To fungovat nebude. Stačí přesunout na začátek a index zvedat až v podmínce po pes =, pak fungovat bude.

Re:Python - Začátečník vs iterace
« Odpověď #3 kdy: 29. 01. 2019, 10:37:20 »
Pánové, děkuji moc za rady, provedl jsem přesun podmínky a již kód funguje, jak bych očekával:

Kód: [Vybrat]
    def __next__(self):
        if self.__index >= len(self.__psi):
            raise StopIteration
        pes = self.__psi[self.__index]
        self.__index += 1
        return pes

Re:Python - Začátečník vs iterace
« Odpověď #4 kdy: 29. 01. 2019, 10:38:56 »
prípadne je možné použiť aj riešenie pomocou výnimky ...

Kód: [Vybrat]
try:
    return self.__psi[self.__index]
except IndexError:
    raise StopIteration
finally:
    self.__index += 1



Re:Python - začátečník vs. iterace
« Odpověď #5 kdy: 29. 01. 2019, 13:30:13 »
Jen pozor, řekněme, že bys chtěl třeba hafany zkombinovat. Zkus si:

stekac = Hafani()
for p in stekac:
    for q in stekac:
        print(p, q)

Kokrspanel Kokrspanel
Kokrspanel Jezevcik
Kokrspanel Ovcak
Kokrspanel Kolie
Kokrspanel Husky

Pro porovnání, co udělá běžný list:

blafac = ["Kokrspanel", "Jezevcik", "Ovcak", "Kolie", "Husky"]
for p in blafac:
    for q in blafac:
        print(p, q)

Kokrspanel Kokrspanel
Kokrspanel Jezevcik
Kokrspanel Ovcak
Kokrspanel Kolie
Kokrspanel Husky
Jezevcik Kokrspanel
Jezevcik Jezevcik
...
Kolie Kolie
Kolie Husky
Husky Kokrspanel
Husky Jezevcik
Husky Ovcak
Husky Kolie
Husky Husky

Každé nové zavolání __iter__ ve tvém iterátoru ti self.__index__ zase resetne na 0.

Re:Python - začátečník vs. iterace
« Odpověď #6 kdy: 29. 01. 2019, 14:51:15 »
v takom prípade treba napríklad použiť ďalšiu triedu s iteratorom. napr.:

Kód: [Vybrat]
class Hafani(object):
    def __init__(self):
        self.__psi = ("Kokrspanel", "Jezevcik", "Ovcak", "Kolie", "Husky")
        self.it = 0
        self.index = []

    def __iter__(self):
        return HafaniIterator(self)

    def psi(self, index):
        return self.__psi[index]


class HafaniIterator:
    def __init__(self, hafani):
        self.__index = 0
        self.hafani = hafani
    def __iter__(self):
        return self
    def __next__(self):
        try:
            return self.hafani.psi(self.__index)
        except IndexError:
            raise StopIteration
        finally:
            self.__index += 1


stekac = Hafani()

for p in stekac:
    for q in stekac:
        print(p,q)

každý for loop dostane svoj iterátor.