Einträge in Dictionary einfügen während Durchführung einer For-Schleife

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
TimeMen
User
Beiträge: 55
Registriert: Samstag 24. Dezember 2016, 10:25
Wohnort: Deutschland

Hallo ihr Lieben,

Folgenden Code habe ich bis jetzt (als Funktion, die dann in das "Hauptskript" importiert wird):

Code: Alles auswählen

#!/usr/bin/env python3
from math import *

def divisor(number):
    result = 0
    for div in range(2, number):
        if number * 10.0 / div % 10 == 0:
            result = result + div
    
    for div in range(2, result):
        if result % div == 0:
            break
Hauptskript:

Code: Alles auswählen

#!/usr/bin/env python3
from math import *
from deflib import divisor

limes = int(input("Limes: "))
for i in range(limes+1):
    divisor(i)
Im Hauptskript habe ich eine Eingabe, z.B. 10, die dann an die Funktion divisor übergeben wird.
In der For-Schleife werden alle echten Teiler von 10 bestimmt, also 2 und 5, da 1 und 10 Trivialteiler von 10 sind, und die Teiler dann mit einander addiert, sodass die Variable result am Ende die Summer aller echten Teiler von 10 enthält. Somit ist result=7 (5+2, 10 und 1 werden ja ausgelassen)

In der zweiten For-Schleife soll dann überprüft werden, ob die Summe result Prim ist oder nicht. Dass lässt sich ja ganz einfach mit Modulo und einer Schleife errechnen. Die Überprüfung könnte man natürlich optimieren indem man die Schleife nur bis zur Wurzel der Summe result laufen lässt, oder überprüft, ob die Summe der echten Teiler 0 ist oder was auch immer. Hier gibt es ja viele verschiedene Verfahren und Tests.

Ist result nun prim, soll die Anfangsnummer 10 und die Echtteilersumme 7 irgendwie zusammen gespeichert werden, sodass beim Abrufen beide Werte angegeben werden. Für meine Zwecke ist denke ich ein Dictionary nicht ganz falsch, da ich ja dann 10 als Schlüssel und 7 als Wert speichern könnte.
Allerdings weiß ich nicht wie ich das hier realisieren soll.

Wenn result nicht prim ist, soll er einfach die Funktion beenden, und dann wird eben die nächste Zahl verarbeitet, da die Funktion divisor ja in einer Schleife aufgerufen wird.


Hoffe ihr könnt nachvollziehen wo mein Problem liegt
LG
TimeMen
Zuletzt geändert von Anonymous am Sonntag 26. Februar 2017, 17:15, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Eine Signatur ist ein Text, der an deine Nachrichten angefügt werden kann. Sie ist auf 300 Zeichen begrenzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@TimeMen: das Berechnen der Teiler ist auch nicht gerade robust, da Du unnötigerweise mit Fließkommazahlen rechnest. Warum nicht einfach ›number % div == 0‹? Die Anfangsnummer kennst Du schon, das ist die Zahl, die Du der Funktion übergibst. Die Echtteilersumme mußt Du ja nur als Rückgabewert zurückgeben. Den Test auf eine Primzahl würde ich in eine eigene Funktion auslagern, weil das ja zwei getrennte Aufgaben sind.
TimeMen
User
Beiträge: 55
Registriert: Samstag 24. Dezember 2016, 10:25
Wohnort: Deutschland

Hallo Sirius,

Stimmt, das sollte eigentlich auch funktionieren beim Berechnen der Teiler.
Den Primzahltest könnte ich auch noch auslagern bei Bedarf.

Aber meine eigentliche Frage, wie ich Zahl und Teilersumme in einem Dictionary speichere, kann ich mir nicht beantworten.
Denn wie ich das geordnet speichern kann weiß ich eben nicht.

LG
TimeMen
Eine Signatur ist ein Text, der an deine Nachrichten angefügt werden kann. Sie ist auf 300 Zeichen begrenzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@TimeMen: Du kennst Dictionaries, weißt aber nicht, wie man sie benutzt?
TimeMen
User
Beiträge: 55
Registriert: Samstag 24. Dezember 2016, 10:25
Wohnort: Deutschland

@Sirius3
Ja, ganz genau so schaut es aus. Ich weiß, dass es in Dictionaries Schlüssel und Werte gibt, aber kann man da mit name.append(x) oder name[3] = "schlüssel":"wert" arbeiten?

Ich habe es gerade mit Listen ausprobiert, was auch nicht so schlecht funktioniert.
Trotzdem wäre ich interessiert, ob obiges mit Dictionaries funktioniert.

LG
TimeMen
Eine Signatur ist ein Text, der an deine Nachrichten angefügt werden kann. Sie ist auf 300 Zeichen begrenzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@TimeMen: weder das eine noch das andere. Wörterbücher werden mit ›name[schlüssel] = wert‹ befüllt.
TimeMen
User
Beiträge: 55
Registriert: Samstag 24. Dezember 2016, 10:25
Wohnort: Deutschland

@Sirius3

Okey, hast du ein Beispiel wie das in meinem Falle anzuwenden wäre? Oder ein allgemeines Beispiel oder ein Codeschnipsel den du schonmal angewendet hast?
Denn ich verstehe das noch nicht so richtig mit dem Zuordnen.
Ansonsten danke auf alle Fälle :), denn mit den Listen klapp es jetzt, ich hatte mich in einer Abfrage vertan und den falschen Wert abgefragt.

LG
TimeMen
Eine Signatur ist ein Text, der an deine Nachrichten angefügt werden kann. Sie ist auf 300 Zeichen begrenzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@TimeMen: wie hast Du das mit Listen gelöst?
TimeMen
User
Beiträge: 55
Registriert: Samstag 24. Dezember 2016, 10:25
Wohnort: Deutschland

@Sirius, hab zwei Listen dafür verwendet. Hatte erst noch durcheinander in den Werten, und mein Primzahltest hat Zahlen durcheinandergeschmissen bzw. 15 und 21 als Primzahlen durchgehen lassen.

Folgendermaßen sieht es jetzt aus: (Wahrscheinlich nicht schön, aber funktioniert. Ich brauche das sowieso nur zum Überprüfen.)

Code: Alles auswählen

#!/usr/bin/env python3
import os

numlist = []
reslist = []

def divisor(number):
    result = 0
    for div in range(2, number):
        if number % div == 0:
            result = result + div
    isPrime(number, result)
    
    
def isPrime(number, result):
    check = 0
    if result >= 2: 
        for div in range(2, result):
            if result % div == 0:
                check = 0
                break
            check = 1
    if check == 1:
        numlist.append(number)
        reslist.append(result)
        
        
def visualize():
    os.system('octave-cli number.m')
    os.system('gwenview --fullscreen limes.png')


limes = int(input(""))
for i in range(limes+1):
    divisor(i)

os.system("rm limes.txt")
file = "limes.txt"
f = open(file, "a")

for i in range(len(numlist)):
    f.write(str(numlist[i]) + ", " + str(reslist[i]) + "\n")

f.close()
visualize()
Wollte für die Aufrufe der Bashbefehle eigentlich "subprocess.call()" nehmen, allerdings bekomme ich da immer eine Fehlermeldung. Kann aber auch an meinem Kubuntu 16.04 liegen. Das spinnt im Moment ein wenig.

LG
TimeMen
Eine Signatur ist ein Text, der an deine Nachrichten angefügt werden kann. Sie ist auf 300 Zeichen begrenzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@TimeMen: Du solltest Funktionen benutzen. Also wirkliche Funktionen, die Rückgabewerte haben. divisor und isPrime haben wirklich nichts miteinander zu tun, die eine Funktion sollte also die andere nicht aufrufen. Für Wahrheitswerte gibt es True und False. Man sollte nicht zusammengehörige Daten in zwei getrennten Listen speichern, sondern Tuple nutzen. Warum löscht Du die Datei (dazu gibt es übrigens os.remove) und öffnest dann die Datei zum Anhängen, statt einfach eine neue leere Datei zu öffnen? Dateien öffnet man am besten mit dem with-Statement. Ausgaben formatiert man mit .format und nicht mit str und +. Über Listen iteriert man direkt und nicht über einen Index.

Code: Alles auswählen

#!/usr/bin/env python3

def divisor(number):
    result = 0
    for div in range(2, number):
        if number % div == 0:
            result += div
    return result
   
def is_prime(number):
    for div in range(2, number):
        if number % div == 0:
            return False
    return True

def main():
    results = []
    limes = int(input())
    for number in range(limes+1):
        divisor_sum = divisor(number)
        if is_prime(divisor_sum):
            results.append((number, divisor_sum))
 
    with open("limes.txt", "w") as output:
        for number, divisor_sum in results:
            output.write("{}, {}\n".format(number, divisor_sum))
       
if __name__ == '__main__':
    main()
oder das ganze etwas kompakter:

Code: Alles auswählen

#!/usr/bin/env python3

def divisor(number):
    return sum(div
        for div in range(2, number)
        if number % div == 0)
   
def is_prime(number):
    return all(number % div != 0 for div in range(2, number))

def iter_divisor_sums(limes):
    for number in range(limes+1):
        divisor_sum = divisor(number)
        if is_prime(divisor_sum):
            yield (number, divisor_sum)

def main():
    limes = int(input())
    with open("limes.txt", "w") as output:
        for number, divisor_sum in iter_divisor_sums(limes):
            output.write("{}, {}\n".format(number, divisor_sum))
       
if __name__ == '__main__':
    main()
Was ist denn das für eine Fehlermeldung, die Du bei subprocess.call bekommst?
TimeMen
User
Beiträge: 55
Registriert: Samstag 24. Dezember 2016, 10:25
Wohnort: Deutschland

Hallo Sirius3,

erstmal danke für die Verbesserungsvorschläge und den verbesserten Code. Mal sehen was ich davon jetzt noch nachvollziehen kann und was nicht ^^
Vor allem mit diesem __xyz__ Kram, und return komme ich nicht klar. An Return habe ich während dem Ausprobieren auch gedacht, allerdings nicht weiter damit probiert. Vielleicht sollte ich mich da mehr einlesen.

Wenn ich subprocess.call verwende, bekomme ich folgenden Fehler, den ich mit os.system nicht bekomme:
[codebox=bash file=Unbenannt.bsh]
Traceback (most recent call last):
File "./number.py", line 37, in <module>
subprocess.call("rm limes.txt")
File "/usr/lib/python3.5/subprocess.py", line 557, in call
with Popen(*popenargs, **kwargs) as p:
File "/usr/lib/python3.5/subprocess.py", line 947, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.5/subprocess.py", line 1551, in _execute_child
raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'rm limes.txt'
[/code]

Und als ich das "rm limes.txt" noch nicht hatte, hat es mir die Werte immer nur hinten angehängt, daher das Löschen des Befehls...
Und wenn das Programm nicht an der Stelle ausgestiegen ist, ist es in der Funktion visualize ausgestiegen, weil da wieder subprocess.call aufgerufen wurde.

Allerdings hast du jetzt ja meine visualize Funktion ausgelassen, in der ich die Befehle ja brauche. Demnach würde bei deinem Verbesserungsvorschlag der Fehler ja nicht auftauchen.
Eine Signatur ist ein Text, der an deine Nachrichten angefügt werden kann. Sie ist auf 300 Zeichen begrenzt.
BlackJack

@TimeMen: Die Werte wurden ja nur deshalb hinten angehängt weil Du die Datei im „append“-Modus geöffnet hast, also in dem Modus wo hinten angehängt wird.

``subprocess.call("rm limes.txt")`` ist falsch. Der Aufruf erwartet entweder den Namen des Programms ohne Argumente, oder eine Liste mit dem Namen des Programms und jedem einzelnen Argument als einzelne Elemente. 'rm limes.txt' ist kein Programmname, darum auch die Meldung das die Datei 'rm limes.txt' nicht gefunden werden konnte. Das Programm heisst ja auch nur 'rm' und 'limes.txt' wäre ein Argument für dieses Programm.

Schau doch einfach mal in die Dokumentation vom `subprocess`-Modul. :-)

Visualisieren würde ich persönlich ja mit `matplotlib` in Python, statt etwas externes aufzurufen. Oder wird da irgend etwas gemacht was sich mit `matplotlib` nicht so einfach erreichen lässt?
TimeMen
User
Beiträge: 55
Registriert: Samstag 24. Dezember 2016, 10:25
Wohnort: Deutschland

Hallo BlackLab,

danke erstmal fürs ändern der Code Tags in meiner Frage (Habs jetzt gefunden, wie man Python Code besser hervorhebt...)
Hab es zwar schonmal im Forum gelesen, war aber länger nicht mehr hier.

Ich rufe die Visualisierung extern auf, weil wir mit Octave arbeiten sollen. Außerdem ist das nur zu Testzwecken. Die Datei lade ich später, sobald ich das fertig habe von Hand in Octave. Theoretisch sollte matplotlib das gleiche können wie Octave, dass ja auch glaube ich auf Python und gnuplot aufbaut.


@Sirius3 Ich werde deine gekürzte Fassung nochmal abwandeln müssen :D
Funktioniert noch nicht ganz die Primzahlen werden nicht rausgeschmissen. Und die haben im Prinzip im Moment in der Ausgabe nichts verloren, weil die mit ihrem Ergebnis nur verwirren. Danke trotzdem :)
Eine Signatur ist ein Text, der an deine Nachrichten angefügt werden kann. Sie ist auf 300 Zeichen begrenzt.
Antworten