Programmierung def mit Teilstringausgabe

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.
Antworten
hkk-micha
User
Beiträge: 5
Registriert: Dienstag 10. Januar 2023, 11:37

Hallo liebe Forengemeinde,

ich bin relativ neu auf dem Gelände des Python-Programmierens und brauche dringend eure Hilfe bei einer Funktion.
Aufgabenstellung ist einen Text bis zu einer Zeichenlänge "l" auf Leerzeichen oder Bindestriche zu untersuchen diese dann mit einem Sonderzeichen zu Trennen "*". In einem weiteren Schritt möchte ich nun den Textteil durch Angabe der Zeile separat ausgeben.

def teiltextl(text,max Zeichen, Index Zeile)
z.B. s= »I love apples, apple are my favorite fruit«

print (teiltext(s,15,2))
>>> Augabe<<<
apple are my

dazu habe ich zwei funktionierende Funktionen die ich allerdings nicht so kombiniert bekomme das es zu meinem Ergebnis passt.

def zeilenumbruch(s, l):
l = int(l)
aus = ""
while len(s) > l:
p = l-1
while p > 0 and s[p] not in " -":
p -= 1
if p == 0:
p = l
aus += s[:p+1] + "*"
s = s[p+1:]
return aus+s

def teil_tz(a,b,c):
c = int(c)
count = a.count(b) + 1
if c > count or c <= 0:
string = " "
else:
substrings = a.split(b)
string = substrings[c - 1]
return string()

Habt Ihr eine Idee? Liebe Grüße Micha
Benutzeravatar
__blackjack__
User
Beiträge: 14065
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@hkk-micha: Die Beschreibung finde ich ja eher verwirrend und die Funktionen auch. Angefangen bei den Namen die fast alle sehr schlecht gewählt sind, über diese ganze Indexhampelei. Kann sein dass da jemand Python lehren will der nicht in Python lehren will — denn Indexzugriffe sind in Python ziemlich selten, weil man die meisten Sachen verständlicher ohne ausdrücken kann.

Dann wandelt man keine Argumente die ganze Zahlen sein sollen *in* der Funktion in ganze Zahlen um. Der *Aufrufer* ist dafür verantwortlich das zu übergeben was erwartet wird.

Und `teil_tz()` funktioniert nicht. Sofern das zum ``return`` kommt, wird dort immer ein ``TypeError: 'str' object is not callable`` die Folge sein.

Kann es sein, dass Du bei einem gegebenen Text Zeilenumbrüche einfügen sollst, damit die Zeilen eine maximale Länge nicht überschreiten? Falls ja, dann schreib das doch auch, und nicht irgendwas mit "*" einfügen.

Als erstes gewöhn Dir vernünftige Namen an. Funktionen werden nach der Tätigkeit benannt, die sie durchführen. Dann weiss der Leser was die tun (sollen) und kann sie auch leicht von eher passiven Werten unterscheiden.

Namen sollten keine kryptischen Abkürzungen enthalten, oder gar nur daraus bestehen. Der Name soll dem Leser verraten was der Wert dahinter für eine Bedeutung hat im Programm. Und nicht zum Rätselraten zwingen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

@hkk-micha: man sollte nicht einfach Eingabeparameter konvertieren. Mit `int` sind auch "23" oder 47.934 gültige Paremter für die Länge, was aber so keinen Sinn macht, oder sogar kontraintuitiv ist.
Bei l-1 ist es besonders schwierig, l und 1 voneinander zu unterscheiden, von daher ist das ein ganz katastrophaler Variablenname.

Das ganze mal besseren Variablenamen ist schon viel lesbarer:

Code: Alles auswählen

def zeilenumbruch(text, laenge):
    ausgabe = ""
    while len(text) > laenge:
        position = laenge - 1
        while position > 0 and text[position] not in " -":
            position -= 1
        if position == 0:
            position = laenge
        ausgabe += text[:position + 1] + "\n"
        text = text[position + 1:]
    return ausgabe + text
Mit regulären Ausdrücken sind das nur drei Zeilen:

Code: Alles auswählen

def zeilenumbruch(text, laenge):
    pattern = "(.{1,%d}$|.{1,%d}[- ]|.{%d})" % (laenge, laenge - 1, laenge)
    ausgabe = re.findall(pattern, text)
    return '*'.join(ausgabe)
Es ist umständlich, erst die Anzahl der Trenner zu zählen, und dann erst zu trennen.
Es ist unpythonisch einen 1-basierten Index zu verwenden, das ist für alle Programmierer sehr verwirrend.
Auch der Default-Rückgabewert " " ist zumindest erklärungsbedürftig.

Code: Alles auswählen

def teil_tz(text, trenner, index):
    substrings = text.split(trenner)
    if 0 < index <= len(substrings):
        return substrings[index - 1]
    return " "
Da es eine split-Methode gibt, ist die Existenz dieser Funktion eh komisch, vor allem, weil die Erklärung, was die Funktion tatsächlich macht, sehr lang werden würde.
hkk-micha
User
Beiträge: 5
Registriert: Dienstag 10. Januar 2023, 11:37

Hi Sirius3 & blackjack,

die Namensgebung ist tatsächlich eine Katastrophe. Die Funktionsentwicklung kommt aus einen Anwenderkreis für Planungssoftware und das merkt man auch :/.
Dank Sirius3 sieht das jetzt schon deutlich besser aus. Vielen lieben Dank!

Jetzt fehlt mir noch noch ein letzter Baustein. Können die beiden Definitionen in einer zusammengefasst werden? Meine Versuche schlagen jedes mal fehl. Ich benötige für meine Anwendung jedoch eine Funktion mit den Eingabeparametern (text, laenge, Trenner(könnte auch auf "*" festgelegt sein ), index ). Habt ihr eine Idee wie ich die Definitionen schachteln kann?

Liebe Grüße
Micha
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du vor einem Problem stehst, dann mußt Du das Problem in kleinere Teile teilen, die trivial zu lösen sind. Die triviale Lösung ist es, hier keine neue Funktion zu schreiben, sondern etwas wegzulassen.
Es macht keinen Sinn, erst in einen String Trennzeichen einzufügen, um danach wieder an diesen Trennzeichen zu trennen, wenn man (eine pythonische Funktion vorausgesetzt) eh schon die Liste mit den Zeilen hat.
hkk-micha
User
Beiträge: 5
Registriert: Dienstag 10. Januar 2023, 11:37

Ok habe ich verstanden. Leider waren die zwei Funktionen mein einziger Anker zur Problemlösung. Eine Definition von Grund auf neu aufzubauen geht über meine Fähigkeiten. Daher suche ich bei euch um dringende Hilfe. Ich weiß das ist viel verlangt :|
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Was fehlt Dir denn jetzt noch an konkreter Hilfe? Es geht ja nur darum, die Funktion `zeilenumbruch` so umzuschreiben, dass sie eine Liste mit den Zeilen zurückliefert.
hkk-micha
User
Beiträge: 5
Registriert: Dienstag 10. Januar 2023, 11:37

Mir ist unklar wie ich die deine optimierte Definition so umschreibe, dass sie eine konkrete Zeile aus der Liste ausgibt.
def zeilenumbruch(text, laenge):
pattern = "(.{1,%d}$|.{1,%d}[- ]|.{%d})" % (laenge, laenge - 1, laenge)
ausgabe = re.findall(pattern, text)
return '*'.join(ausgabe)
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Dir das unklar ist, fange am besten mit einem Einführungstutorial in Python an. Dort wird Dir erklärt, was Listen sind.
hkk-micha
User
Beiträge: 5
Registriert: Dienstag 10. Januar 2023, 11:37

Mache ich! Dennoch wäre ich dir sehr dankbar wenn du den bereits oben verbesserten Code um die Listenausgabe erweitern könntest. Bitte bitte bitte :wink:
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wir liefern keine Hausaufgaben frei Haus. Zeig, was du probierst, und dann kann man dir auf die Spruenge helfen.
Antworten