@Chazy: Der Code mag funktionieren, ist aber nicht so besonders.
Erstmal für andere die den vielleicht mal ausprobieren wollen die Quelle für das `graphics`-Modul:
http://mcsp.wartburg.edu/zelle/python/
Die Form, also zum Beispiel Namenskonventionen, Leerzeichen, und Einrückung entsprechen nicht dem
Style Guide for Python Code.
Die Namen sind überwiegend auch sehr schlecht. Die lokalen Namen viel zu kurz und nichtssagend und die Funktionsnamen nicht immer passend zu dem was die Funktion tut.
Sternchenimporte sollte man vermeiden. Damit werden Programme ganz schnell unübersichtlich, weil man nicht einfach heraus finden kann aus welchem Modul welcher Name kommt. Ausserdem bekommt man Probleme wenn verschiedene Module gleiche Namen enthalten. Man sollte entweder die Objekte die man verwendet explizit importortieren oder nur das Modulobjekt und über das dann auf die enthaltenen Objekte zugreifen.
`binClock()` ist übermässig umständlich. Hast Du Dir das Ergebnis von `localtime()` denn nicht mal angeschaut? Warum dieser unsinnige Umweg über eine Zeichenkette mit `strftime()` um die dann wieder in eine Zahl zu wandeln. Wobei dort das „slicing” der Zeichenkette total überflüssig ist.
Des weiteren enthält die Funktion eine „race condidion” die zu falschen Zeitanzeigen führen kann. Wenn der erste `localtime()`-Aufruf ganz am Ende einer 59sten Minute erfolgt und der zweite Aufruf schon in der darauf folgenden Minute, dann passen Minute und Stunde nicht mehr zusammen. Dann wird zum Beispiel 10:59 Uhr angezeigt obwohl es erst 10:00 Uhr ist.
`h` und `m` mögen hier zwar noch ”verständlich” sein, ich würde sie aber trotzdem `hour` und `minute` nennen. Namen sollen dem Leser möglichst deutlich vermitteln was die Werte dahinter bedeuten.
Anstelle des `time`-Moduls was eine relativ dünne Schicht über die Zeitfunktionen der C-Bibliothek darstellt, würde ich persönlich das `datetime`-Modul verwenden.
Funktionsnamen sollten Tätigkeiten beschreiben, was der Name `binClock()` nicht ist.
In `calcTime()` sind es dann wieder die lokalen Namen. Hier machen sie das Ganze IMHO nahezu unlesbar. Dazu dass sie kurz und absolut nichtssagend sind kommen noch die Zeichen 1 und l die in vielen Schriftarten so ähnlich sind, dass man sie nur mit Mühe auseinanderhalten kann.
Zum Algorithmus ist zu sagen, dass sich hier Code wiederholt der sich nicht wiederholen sollte. Und insgesamt ist der Algorithmus der sich über `calcTime()` und `timeToList()` erstreckt total überkompliziert. Eine Zahl in eine Liste mit Bits umzusetzen ist eigentlich *eine* Schleife. Man itertiert über die Zweierpotenzen und testet mit Bitoperationen ob das jeweilige Bit gesetzt ist oder nicht und fügt dementsprechend das passende Zeichen der Liste hinzu. Das war's. Eventuell muss man die Liste danach noch umdrehen wenn man die Zweierpotenzen aufsteigend erzeugt hat. *Erzeugt* und nicht per Hand in eine Liste geschrieben.
Was machen die ``while True:``-Schleifen in `calcTime()` eigentlich? Wie oft werden die *immer* durchlaufen?
```for i in range(len(sequence)):`` ist in Python ein „anti pattern”. In 99,99% der Fälle macht man da etwas falsch, denn man braucht nur recht selten *nur* den Index innerhalb der Schleife. Man kann über Elemente von Sequenzen direkt iterieren, ohne den Umweg über einen Index. Wenn man denn Index *zusätzlich* braucht, gibt es die `enumerate()`-Funktion.
Überhaupt ist `timeToList()` „unpythonisch”. Man erzeugt in der Regel keine Listen mit Objekten die man eigentlich gar nicht benötigt weil sie im nachfolgenden Code der Reihe nach durch andere Werte ersetzt werden. In solchen Fällen fängt idiomatisches Python mit einer leeren Liste an, an die die Werte die da am Ende auch stehen sollen angehängt werden. Eventuell das ganze auch als „list comprehension” formuliert wo es sich anbietet.
Dann überschreibst Du die nicht benötigten Zahlen erst einmal komplett mit ' ', wobei auch hier Werte an Stellen geschrieben werden, die später wieder durch andere Ersetzt werden. Statt gleich in *einer* Schleife zu entscheiden welcher Wert an welchen Platz kommen soll.
Die Schleifen für die 'X' sind vom Laufzeitverhalten sehr unschön. die `index()`-Methode sucht linear nach dem Wert.
Letztendlich sind beide Funktionen überflüssig weil man mit der `format()`-Funktion auf Zeichenketten Zahlen in eine Binärdarstellung aus '0' und '1' formatieren kann.
In `clockView()` ist zu viel von Hand geschriebener Code beziehungsweise Kopieren und Einfügen. Die beiden Listen mit den Kreisen liessen sich so einfach per Code erstellen statt jeden Kreis per Hand zu schreiben. Stell Dir mal den Aufwand vor die Kreisgrösse, -position, oder den Abstand bei Deinem Quelltext verändern zu müssen. Grössen oder Abstände die von anderen Werten abhängen sollten vom Programm berechnet werden und nicht vom Programmierer. Hier läge IMHO die Hauptkomplexität bei dem Programm.
Das eine Funktion die jeweils nächste aufruft ist nicht gut. So lassen sich die einzelnen Funktionen weder separat testen, noch wiederverwenden, weil jeder Aufruf immer die anderen Aufrufe nach sich zieht.
Das Programm könnte dann so aussehen:
Code: Alles auswählen
#!/usr/bin/env python
from graphics import Circle, GraphWin, Point
from time import localtime
def get_binary_time(time=None):
now = localtime(time)
return ('{0:04b}'.format(now.tm_hour), '{0:06b}'.format(now.tm_min))
def display_binary_values(binary_values):
padding = 50
radius = 10
min_distance = 10
diameter = 2 * radius
max_circles = max(map(len, binary_values))
width, height = (
(diameter + min_distance) * x - min_distance + 2 * padding
for x in [max_circles, len(binary_values)]
)
window = GraphWin('BinaryClock', width, height)
for row_number, digits in enumerate(binary_values):
spacing = (width - 2 * padding - diameter) / (len(digits) - 1)
y = padding + radius + (diameter + min_distance) * row_number
for i, digit in enumerate(digits):
circle = Circle(
Point(int(i * spacing) + padding + radius, y),
radius
)
if digit == '1':
circle.setFill('blue')
circle.draw(window)
window.getMouse()
window.close()
def main():
display_binary_values(get_binary_time())
if __name__ == '__main__':
main()
In die Dokumentation gehört dann wahrscheinlich eine Zeichnung an welcher die Berechnungen für die Grafik deutlich gemacht werden.
Was die Android-App angeht: Das würde ich entweder „nativ” machen, also in Java, oder als HTML5-App in JavaScript. Bevorzugt letzteres, weil das unabhängiger vom Gerät ist.