Unerklärlicher Typfehler

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
DopaminZH
User
Beiträge: 14
Registriert: Samstag 6. Dezember 2014, 00:29

Hallo ich komme nicht weiter:

Code: Alles auswählen

def suche(num, vorwahl):
    if len(num) == 1:
        if num[0][:len(vorwahl)] == vorwahl:
            return num
        else:
            return []
    else:
        return suche(num[:len(num)/2], vorwahl)+suche(num[len(num)/2:], vorwahl)

nummernliste = ['0223 788834', '0201 566722', '0224 66898', '0201 899933', '0208 33987']

print(suche(nummernliste, '0201'))
Die Ausgabe sollte sein:

['0201 566722', '0201 899933']

Aber es tritt folgender Fehler auf:

line 8, in suche
return suche(num[:len(num)/2], vorwahl)+\
TypeError: slice indices must be integers or None or have an __index__ method

Wo liegt das Problem? len(num) in der Konsole ist 5 also Integer.
Zuletzt geändert von DopaminZH am Donnerstag 1. Januar 2015, 01:45, insgesamt 1-mal geändert.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Ich vermute, dass du den Test mit Python 2 und das Programm mit Python 3 ausführst. Unter Python 3 bekommst du float-Ergebnisse.

Code: Alles auswählen

>>> num = '0223 788834'
>>> num[:len(num)/2]
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    num[:len(num)/2]
TypeError: slice indices must be integers or None or have an __index__ method
>>> len(num)/2
5.5
Verwende explizite Integer-Division.

Code: Alles auswählen

>>> len(num)//2
5
BlackJack

@DopaminZH: Anstelle von diesem hier ``num[0][:len(vorwahl)] == vorwahl`` würde man besser ``num[0].startswith(vorwahl)`` verwenden. Das erspart das erstellen einer neuen Teilzeichenkette zum Vergleichen. Und in der Praxis würde man das auch nicht rekursiv und mit so verdammt vielen erstellten/kopierten Teillisten machen sondern einfach eine „list comprehension” schreiben. Also einfach:

Code: Alles auswählen

print([n for n in nummern if n.startswith('0201')])
Da braucht man nicht mal eine extra `suche()`-Funktion für. Die Rekursion ist komplett unsinnig. Das ist nicht einmal theoretisch effizienter oder sinnvoll.
DopaminZH
User
Beiträge: 14
Registriert: Samstag 6. Dezember 2014, 00:29

/me hat geschrieben:Ich vermute, dass du den Test mit Python 2 und das Programm mit Python 3 ausführst. Unter Python 3 bekommst du float-Ergebnisse.

Code: Alles auswählen

>>> num = '0223 788834'
>>> num[:len(num)/2]
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    num[:len(num)/2]
TypeError: slice indices must be integers or None or have an __index__ method
>>> len(num)/2
5.5
Verwende explizite Integer-Division.

Code: Alles auswählen

>>> len(num)//2
5
Das dachte ich noch..danke
DopaminZH
User
Beiträge: 14
Registriert: Samstag 6. Dezember 2014, 00:29

BlackJack hat geschrieben:@DopaminZH: Und in der Praxis würde man das auch nicht rekursiv und mit so verdammt vielen erstellten/kopierten Teillisten machen sondern einfach eine „list comprehension” schreiben. Also einfach:

Code: Alles auswählen

print([n for n in nummern if n.startswith('0201')])
Da braucht man nicht mal eine extra `suche()`-Funktion für. Die Rekursion ist komplett unsinnig. Das ist nicht einmal theoretisch effizienter oder sinnvoll.
Danke Dir. Ist aus dem Buch:

http://www.amazon.de/Python-Lernen-prof ... 3826694562
BlackJack

Wenn das tatsächlich aus dem Buch ist das bin ich etwas verwundert weil das hier sonst eigentlich einen ganz guten Ruf zu scheinen hat.
DopaminZH
User
Beiträge: 14
Registriert: Samstag 6. Dezember 2014, 00:29

Es ist soweit auch ein gutes Buch (mal abgesehen von dem Fehler eben). Hab es via GoogleBooks auch auf dem Handy. Man könnte dort auch Notzen einfügen (gerade in diesem Fall praktisch)... leider funktioniert das nicht wie es soll... zB eingetragen auf dem Handy sind sie aufem PC an einer anderen Stelle...schade
BlackJack

@DopaminZH: Es geht nicht um den Fehler sondern um die Funktion an sich. Die ist absolut gruselig und sinnfrei. Ausser wenn man zeigen möchte wofür man Rekursion ganz bestimmt *nicht* verwenden sollte, in der Form nicht einmal in einer funktionalen Programmiersprache. Und ineffizient ist das mit dem slicen in Python auch noch.
DopaminZH
User
Beiträge: 14
Registriert: Samstag 6. Dezember 2014, 00:29

Sieht schon deutlich einfacher aus, danke nochmal :wink:

Code: Alles auswählen

nummernliste = ['0223 788834', '0201 566722', '0224 66898', '0201 899933', '0208 33987']
print([n for n in nummernliste if n.startswith('0201')])
Die comprehension list wird im Buch 3 Seiten weiter erklärt:
liste = [ausdruck for element in andereliste if bedingung]

Code: Alles auswählen

c = [i for i in range(50) if i%7 == 0]
>>> c
[0, 7, 14, 21, 28, 35, 42, 49]
Zuletzt geändert von DopaminZH am Donnerstag 1. Januar 2015, 04:46, insgesamt 1-mal geändert.
BlackJack

@DopaminZH: Die Ausnahmen haben offenbar nichts mit Deinem Code zu tun. Generelle Beobachtung: Zum Ausführen von Python-Programmen kann man viele IDEs in die Tonne treten. :-) Ich führe Konsolenprogramme in einer ganz normalen Konsole aus, dann weiss ich auch wie die sich dort verhalten, und das keine IDE irgendwie dazwischen funkt und komische Sachen macht.
DopaminZH
User
Beiträge: 14
Registriert: Samstag 6. Dezember 2014, 00:29

BlackJack hat geschrieben:@DopaminZH: Die Ausnahmen haben offenbar nichts mit Deinem Code zu tun.
Nach dem PyCharm Neustart waren die Ausnahmen verschwunden....sorry :wink:

Welche IDE's sind brauchbar?
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

DopaminZH hat geschrieben:Welche IDE's sind brauchbar?
Wie BlackJack schon sagte: Auf der verlässlichsten Seite bist Du, wenn Du direkt auf der Pythonkonsole bzw. Konsole testest. In manchen Fällen (Encoding/Escapesequenzen) hatte ich sogar auf der IPythonkonsole eigenartiges Verhalten.
Und 'ne IDE in dem Sinn brauchst Du unter Python ja eh nicht wirklich. Editor mit Syntaxhighlighting und vielleicht noch -prüfung links, Konsole rechts reichen doch eigentlich, oder?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Debugging oder Referenzieren von Code ist bei PyCharm wesentlich angenehmer. Auch die Codeprüfung und Codeergänzung nimmt einen viel Arbeit ab. So sinnlos sind also IDEs in Python nicht.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@darktrym
Wie so oft: Ansichtssache. Mein persönliches Resümee nach verschiedenen "IDE-Ausflügen" ist: Ordentlicher Editor mit dem einen oder anderen Plugin reicht vollkommen. Wobei es natürlich auch eine Frage der Definition ist, was man unter IDE versteht. Das reicht ja von Editor + Plugins bis zu Eclipse...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Ich nutze PyCharm selbst nur für das Debugging sonst ist mir die IDE viel zu träge.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
DopaminZH
User
Beiträge: 14
Registriert: Samstag 6. Dezember 2014, 00:29

BlackJack hat geschrieben:Wenn das tatsächlich aus dem Buch ist das bin ich etwas verwundert weil das hier sonst eigentlich einen ganz guten Ruf zu scheinen hat.
Es hat weniger schlimme (...Schönheitsfehler zB Abstand zwischen xyz (), aber leider auch richtige Fehler, wobei die meisten in den mitgelieferten Code-Beispielen korrigiert wurden, schon recht peinlich, aber leider nicht alle. Gerade für Anfänger mühsam......

Beispiel:

Code: Alles auswählen

class Geld(object):
    __wechselkurs={'USD':0.84998,
                   'GBP':1.39480,
                   'EUR':1.0,
                   'JPY':0.007168} 
    def __init__(self, waehrung, betrag):
        self.__waehrung = waehrung
        self.__betrag = float(betrag)

    def getBetrag(self):
        return self.__betrag

    def getWaehrung(self):
        return self.__waehrung

    def getEuro(self):                                 
        return self.__betrag *   \
              self.__wechselkurs[self.__waehrung]

    def setWaehrung(self, neueWaehrung):
        if neueWaehrung in self.__wechselkurs.keys():
            alt = self.__wechselkurs[self.__waehrung]
            neu = self.__wechselkurs[neueWaehrung]
            self.__betrag = alt/neu * self.__betrag
            self.__waehrung = neueWaehrung
      
    def __add__(self, geld):
        summe_in_Euro = self.getEuro()+geld.getEuro()
        summe = Geld1(self.__waehrung,   # ============> sollte nur Geld sein oder?
             summe_in_Euro/self.__wechselkurs[self.__waehrung])

        return summe

    def __str__(self):
        text = 'Das addierte Objekt hat einen Wert von ' + str(self.getBetrag())
        return text
Trotz der Fehler ist es alles in allem gut.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@DopaminZH: die doppelten Unterstriche im Beispiel sollten einfache sein. Nach Namenskonvention sollte es get_betrag, usw. heißen, die __str__ Funktion gibt das falsche aus, weil der Betrag auch für nicht-addierte Objekte gilt. Dieses Deutsch-Englisch-Mischmasch ist auch seltsam. Allgemein würde ich die Klasse unveränderlich halten und statt set_waehrung eine change-Funktion schreiben:

Code: Alles auswählen

from collections import namedtuple

class Money(namedtuple("Money", "amount, currency")):
    EXCHANGE_RATES = {
        'USD': 0.84998,
        'GBP': 1.39480,
        'EUR': 1.0,
        'JPY': 0.007168,
    }

    def change(self, new_currency):
        factor = self.EXCHANGE_RATES[self.currency] / self.EXCHANGE_RATES[new_currency]
        return type(self)(self.amount * factor, new_currency)

    def __add__(self, other):
        return type(self)(self.amount + other.change(self.currency).amount, self.currency)

    def __str__(self):
        return '{0.amount:.2f} {0.currency}'.format(self)
DopaminZH
User
Beiträge: 14
Registriert: Samstag 6. Dezember 2014, 00:29

Danke, wie erwähnt, bin Anfänger ;-) Drum verstehe nicht was....

type(self) vor der Berechnung

....zu bedeuten hat.

Als PyCharm Watch gibt es folgendes aus:

Bild

werde daraus nicht schlau...
BlackJack

@DopaminZH: Die `type()`-Funktion ermittelt den Typ des Arguments. Also in diesem Fall `Money`. Und nun überleg mal was passiert wenn Du eine Unterklasse von `Money` ableitest.
DopaminZH
User
Beiträge: 14
Registriert: Samstag 6. Dezember 2014, 00:29

....dass dann nach den Unterklassen-Werten/Attibuten/Methoden gerechnet würde...?
Antworten