Posts by __blackjack__
-
-
Humpelschlumpf An der Klasse ist schon mal falsch das `sensor_constants` eine Klassenvariable und damit global ist und für alle Exemplare gilt.
Dann werden `temperature` und `pressure` ausserhalb der `__init__()` eingeführt und durch `measure()` sowohl gesetzt als auch zurückgegeben. Das ist wirr und verwirrend.
`calculate_altitude()` steckt als reine Funktion in der Klasse. Wird aber auch gar nicht verwendet. Auch `crc8` hat als Funktion in der Klasse nichts zu suchen.
Die `rdwr()`-Methode ist sowohl was die Argumente als auch die Rückgabewerte angeht ein bisschen sehr flexibel. Für meinen Geschmack zu flexibel. Mindestens der Rückgabewert sollte konsistent eine Liste mit Zahlen sein, statt manchmal auch eine einzelne Zahl.
Was genau verstehst Du denn nicht? Mal davon abgesehen, dass die IMHO zu viel macht, ist das was sie macht, ja nicht so besonders kompliziert.
Ungetesteter, überarbeiteter Quelltext:
Python
Display Moreimport struct import time from smbus2 import SMBus, i2c_msg __version__ = "0.0.1" NORMAL = 0x6825 LOW_POWER = 0x609C LOW_NOISE = 0x70DF ULTRA_LOW_NOISE = 0x7866 NORMAL_T_FIRST = 0x6825 NORMAL_P_FIRST = 0x48A3 LOW_POWER_T_FIRST = 0x609C LOW_POWER_P_FIRST = 0x401A LOW_NOISE_T_FIRST = 0x70DF LOW_NOISE_P_FIRST = 0x5059 ULN_T_FIRST = 0x7866 ULN_P_FIRST = 0x58E0 SOFT_RESET = 0x805D READ_ID = 0xEFC8 MOVE_ADDRESS_PTR = 0xC595 READ_OTP = 0xC7F7 DEFAULT_I2C_ADDRESS = 0x63 CHIP_ID = 0x08 MEASUREMENT_DELAYS = { NORMAL: 7, # 5.6 to 6.3ms LOW_POWER: 2, # 1.6 to 1.8ms LOW_NOISE: 24, # 20.8 to 23.8ms ULTRA_LOW_NOISE: 95, # 83.2 to 94.5ms } def crc8(data, polynomial=0x31): result = 0xFF for byte in data: result ^= byte for _ in range(8): result <<= 1 if result & 0x100: result ^= polynomial return result & 0xFF class ICP10125: def __init__(self, bus_number, address=DEFAULT_I2C_ADDRESS): self.address = address self.bus = SMBus(bus_number) chip_id = self.chip_id() if chip_id != CHIP_ID: raise RuntimeError( f"ICP10125: Invalid Chip ID {chip_id:02x}, " f"expected: {CHIP_ID:02x}" ) self.sensor_constants = self.read_otp() def rdwr(self, command, length=0, delay=0): if isinstance(command, int): message = i2c_msg.write(self.address, struct.pack(">H", command)) else: message = i2c_msg.write(self.address, command) self.bus.i2c_rdwr(message) time.sleep(delay / 1000) if length > 0: message = i2c_msg.read(self.address, length) self.bus.i2c_rdwr(message) if length == 1: return message.buf[0] else: data = [] result = list(message) for index in range(0, len(result), 3): if crc8(result[index : index + 2]) != result[index + 2]: raise ValueError("ICP10125: Invalid CRC8 in response.") data.append((result[index] << 8) | result[index + 1]) if len(data) == 1: return data[0] else: return data return [] def chip_id(self): return self.rdwr(READ_ID, 3) & 0x3F def read_otp(self): self.rdwr( [ MOVE_ADDRESS_PTR >> 8, MOVE_ADDRESS_PTR & 0xFF, 0x00, 0x66, 0x9C, # Address CRC8 ] ) return [self.rdwr(READ_OTP, 3) for _ in range(4)] def reset(self): self.rdwr(SOFT_RESET, delay=0.1) def calculate_conversion_constants(self, p_lut): p_pa = [45_000, 80_000, 105_000] c = ( p_lut[0] * p_lut[1] * (p_pa[0] - p_pa[1]) + p_lut[1] * p_lut[2] * (p_pa[1] - p_pa[2]) + p_lut[2] * p_lut[0] * (p_pa[2] - p_pa[0]) ) / ( p_lut[2] * (p_pa[0] - p_pa[1]) + p_lut[0] * (p_pa[1] - p_pa[2]) + p_lut[1] * (p_pa[2] - p_pa[0]) ) a = ( p_pa[0] * p_lut[0] - p_pa[1] * p_lut[1] - (p_pa[1] - p_pa[0]) * c ) / (p_lut[0] - p_lut[1]) return a, (p_pa[0] - a) * (p_lut[0] + c), c def process_data(self, pressure, temperature): lut_lower = 3.5 * (1 << 20) lut_upper = 11.5 * (1 << 20) quadr_factor = 1 / 16777216 offst_factor = 2048 t = temperature - 32768 a, b, c = self.calculate_conversion_constants( [ lut_lower + (self.sensor_constants[0] * t * t) * quadr_factor, ( offst_factor * self.sensor_constants[3] + (self.sensor_constants[1] * t * t) * quadr_factor ), lut_upper + (self.sensor_constants[2] * t * t) * quadr_factor, ] ) return (a + b / (c + pressure), -45 + 175 / 65536 * temperature) def measure(self, measure_command=NORMAL): result = self.rdwr( measure_command, 9, MEASUREMENT_DELAYS[measure_command] ) return self.process_data( (result[1] << 8) | (result[2] >> 8), result[0] )
-
shamzi097 ”Schnittstellenklase” klingt als würde hier jemand versuchen Java in Python zu schreiben. Das sollte man nicht machen. Entweder hat meine Abstrakte Klasse die auch tatsächlich Teilfunktionalität implementiert, oder man hat einfach gar keine Klasse, sondern Dokumentation die das Protokoll beschreibt, was die Funktion oder Methode von solchen Werten erwartet.
Die Verwendung von `type()` macht hier keinen Sinn. Das die richtige Methode auf dem richtigen Typ aufgerufen wird, passiert doch schon automatisch wenn man einfach die Methode auf dem Wert aufruft. Das muss man sich nicht noch mal nachprogrammieren.
Pythondef get_social_results(self, query=""): social_types = self.types["social"] return igrabber.cycle_grabber( execute_chain_results( [social_type.request for social_type in social_types], [(query, 0)] * len(social_types), ) )
Die API von `execute_chain_results()` ist komisch, das man da zwei ”parallele” Listen übergeben muss. Besser wäre eine Sequenz (oder gar nur etwas iterierbares) über aufrufbare Objekte, die ihre Argumente bereits kennen. Diese Bindung kann man beispielsweise mit `functools.partial()` machen. Könnte dann so aussehen:
-
Was ist denn der Grund da so eine umfangreiche mechanische Lösung zu bauen? Das dürfte etwas sein, was man schön in einem Prototyp zeigen kann, was in der Praxis aber ständig die Haustechnik beschäftigt, weil einzelne Elemente hängen bleiben, oder was kaputt keinen guten Eindruck macht, wenn es nicht gewartet wird.
-
Der Code sieht auf jeden Fall so aus als sollte man da mal nummerierte Namen loswerden und die Codewiederholungen durch eine Schleife ersetzen.
Wieviel RAM wird denn für den Videochip reserviert? Drei Bilder in der Auflösung belegen alleine ja schon 44½ MiB und der Desktop braucht ja auch noch Speicher.
-
Allgemeine Anmerkung zum Ausgangscode: Die ganzen `cmd_*`-Attribute sind ja eigentlich Konstanten. Also solche würde man die auch definieren. Entweder auf der Klasse oder im Modul und der Namenskonvention folgend KOMPLETT_GROSS geschrieben, oder man erstellt sich einen Aufzählungstypen mit `enum.IntEnum`.
Einen Wahrheitswert mit ``if flag > 0:`` zu prüfen geht zwar, ist aber irreführend. Das ist einfach nur ``if flag:``. Um die Bedingung gehören auch keine Klammern.
`draw_function()` und `draw_scatter()` verwenden eine unnötige Indirektion über einen Laufindex, was in Python ein „anti pattern“ ist, weil man direkt über die Elemente von Sequenzwerten iterieren kann. Ausserdem sind die beiden Methoden fast identisch, das sollte nicht sein. Da gibt es noch ein paar andere Methoden die kopiert und geringfügig angepasst aussehen.
-
Also in Python könnte das so aussehen (was auch immer die Programmiersprache mit den Klammern um die Bedingungen und den schlechten Namen ist 😛):
Python
Display More#!/usr/bin/env python3 from itertools import count def is_armstrong_number(number): digits = str(number) exponent = len(digits) return ( sum(digit_value**exponent for digit_value in map(int, digits)) == number ) def main(): for armstrong_number in filter(is_armstrong_number, count()): print(armstrong_number) if __name__ == "__main__": main()
Das sucht einfach unendlich. Falls man das auf einen Zahlenbereich einschränken möchte, müsste man `count()` durch ein entsprechendes `range()` ersetzen.
-
Dieser Benutzer trägt irgendwie nix sinnvolles zu diesem Forum bei. Die Frage ist unverständlich. Auf die Nachfrage wird nicht eingegangen. Der Code im letzten Beitrag — angeblich die Lösung — kommt so nicht einmal am Compiler vorbei, weil da mehrere Syntaxfehler drin sind.
Wenn man die Syntaxfehler korrigiert und das Programm ausführt, kommt auch nicht die behauptete Ausgabe, sondern eine Ausnahme, die das Programm in Zeile 20 abbricht, weil in Zeile 5 von `source` der Name `f` undefiniert ist:
CodeTraceback (most recent call last): File "test2.py", line 20, in <module> exec ( source, globals_dict, locals_dict ) File "<string>", line 5, in <module> NameError: name 'f' is not defined
Das ist die einzige Ausgabe, da die `print()`-Aufrufe erst danach kämen. Würde man diese Ausnahme behandeln in dem man sie mehr oder weniger ignoriert, dann läuft man beim erstellen von `var_values` in die nächste Ausnahme, weil beim analysieren vom AST zwar die Zuweisung an `c` gefunden, und damit der Name statisch bekannt ist, aber der Code durch die Ausnahme wegen `f` natürlich nicht so weit kommt, das `c` dann auch definiert wird:
CodeTraceback (most recent call last): File "test2.py", line 24, in <module> var_values = { var_name: locals_dict [ var_name ] for var_name in var_names } File "test2.py", line 24, in <dictcomp> var_values = { var_name: locals_dict [ var_name ] for var_name in var_names } KeyError: 'c'
Das macht alles wenig bis gar keinen Sinn.
-
Werner43 Du schreibst Du hast das nach der Anleitung in dem Link installiert, dort werden aber *vier* Alternativen beschrieben. Welche davon hast Du denn installiert?
Und was heisst remote genau? Du bist per SSH angemeldet und versuchst darüber eine grafische Anwendung zu starten? Wo soll das denn angezeigt werden? Da muss irgendwo ein X-Server laufen und die DISPLAY-Umgebungsvariable entsprechend gesetzt sein.
-
KaptainAhoibrause Im Terminal kann man DOSBox ja auch nicht ausführen, das braucht Grafik in irgendeiner Form. Vom Terminal aus könntest Du versuchen das Programm mit Strg+C abzubrechen. Ansonsten müsste man auf eine andere Konsole wechseln und dort neustarten oder herunterfahren.
-
AndrePi Mit dem `psutil`-Modul kann man sich mit der `net_if_addrs()`-Funktion die Interfaces und IPs geben lassen. "Die" IP gibt es so ja nicht, der Pi hat von Haus aus ja schon WLAN und Ethernet und heute gibt es in der Regel eine IPv4 und eine IPv6 IP pro Interface.
Dir externe IP kann man in der Regel auch vom Router abfragen, dann ist man nicht auf externe Webseiten angewiesen.
-
Jup, es scheinen da tatsächlich immer nur sechs Tage dazwischen zu liegen. Es ist erschreckend wie schnell die Zeit rennt. 😉
-
Zentris Du stellst das etwas verzerrt dar, als wenn es irgendwie gefährlich werden könnte was Du in der Cloud privat speicherst. Es geht da nicht darum das Privatpersonen abgemahnt werden, für Sachen die ja auch gar nicht öffentlich zugänglich sind, sondern die Verwertungsgesellschaften bekommen pauschalen für jeden verkauften Datenträger vom *Hersteller*, völlig unabhängig wie der genutzt wird, weil da könnten und werden ja von vielen Leuten auch Privatkopien von urheberrechtlich geschützten Material gespeichert. Und das wollen die jetzt auch gerne auf die Cloud ausdehnen. Also das die Cloudanbieter pauschale Abgaben zahlen müssen. Das betrifft uns Endanwender nur indirekt, weil die Abgaben natürlich dann am Ende im Preis landen.
-
`MemoryError` heisst der Arbeitsspeicher ist voll.
-
Der Icon-Code im anderen Thema bringt ja nicht wirklich Neues. Der Icon-Quelltext zurück nach Python übersetzt sieht letztlich genau so aus wie das was hier auf der ersten Seite schon stand — nur noch ineffizienter was den Speicherverbrauch angeht als eine Liste mit 1en und 0en:
Python
Display More#!/usr/bin/env python3 import math def main(): # liste = [(1, 2), (1, 3), (1, 5), (1, 7), (1, 11)] liste = [(1, 2), (1, 3), (1, 5), (1, 7), (1, 11), (17, 121), (1, 991)] kgv = math.lcm(*(modul for _, modul in liste)) print("kgV =", kgv) restklassen = set(range(1, kgv)) for index, step in liste: for index in range(index, kgv, step): restklassen.discard(index) print(f"Anzahl der Restklassen zu {liste} ==> {len(restklassen)}") if __name__ == "__main__": main()
Die Menge durch eine Liste ersetzt und das Beispiel läuft hier ca. 3× schneller und verbraucht nur 205 MB statt 2,2 GB Arbeitsspeicher. Und ich denke nicht, dass das schwerer verständlich ist:
Python
Display More#!/usr/bin/env python3 import math def main(): # liste = [(1, 2), (1, 3), (1, 5), (1, 7), (1, 11)] liste = [(1, 2), (1, 3), (1, 5), (1, 7), (1, 11), (17, 121), (1, 991)] kgv = math.lcm(*(modul for _, modul in liste)) print("kgV =", kgv) restklassen = [1] * kgv restklassen[0] = 0 for index, step in liste: for index in range(index, kgv, step): restklassen[index] = 0 print(f"Anzahl der Restklassen zu {liste} ==> {sum(restklassen)}") if __name__ == "__main__": main()
Mit einem Bitvektor sinkt der Speicherverbrauch für die Liste mindestens um den Faktor 8, dafür steigt die Rechenzeit — zumindest wenn der Bitvektor in Python implementiert ist, weil das berechnen der Bitpositionen und maskieren der Bits natürlich etwas mehr Zeit verbraucht als einfach eine 0 an einem Index zuzuweisen. Wobei man da wohl von der hier schon verwendeten BitVector-Klasse deutlich abraten sollte, denn das folgende Programm braucht damit bei mir 27 MB *mehr* Speicher als die Liste mit 1en und 0en und *deutlich* mehr Rechenzeit: 29× mehr als mit der Liste:
Python
Display More#!/usr/bin/env python3 import math from BitVector import BitVector def main(): # liste = [(1, 2), (1, 3), (1, 5), (1, 7), (1, 11)] liste = [(1, 2), (1, 3), (1, 5), (1, 7), (1, 11), (17, 121), (1, 991)] kgv = math.lcm(*(modul for _, modul in liste)) print("kgV =", kgv) restklassen = ~BitVector(size=kgv) restklassen[0] = 0 for index, step in liste: for index in range(index, kgv, step): restklassen[index] = 0 print(f"Anzahl der Restklassen zu {liste} ==> {sum(restklassen)}") if __name__ == "__main__": main()
-
hyle Ups. Das war direkt im Beitragseditor eingetippt.
-
Falls es okay ist, das man den Fall das *keine* "#"-Zeile vorkommt, nicht davon unterscheiden kann, dass dies die *letzte* Zeile ist, und das es nur eine "#"-Zeile geben darf, ginge wohl auch das hier:
-
Unter der Voraussetzung, dass es mindestens ein "#" gibt und die Zeilen mit Zeilenenden abgeschlossen sind, wäre eine kurze Lösung:
Pythonwith open("test.txt", encoding="utf-8") as file: lines = list(file) print(len(lines) - lines.rindex("#\n"))
Falls es keine "#"-Zeile gibt, löst das einen `IndexError` aus.
Alternativ, falls man etwas mehr Code schreiben will, aber weniger Speicher verbrauchen möchte, weil man ja nicht alle Zeilen auf einmal im Speicher dafür braucht:
Pythonwith open("test.txt", encoding="utf-8") as lines: line_count = None for line in lines: if line.rstrip() == "#": line_count = 0 if line_count is not None: line_count += 1 print(line_count)
Das gibt, falls gar kein "#"-Zeile enthalten ist, den Wert `None` aus.
-
fred0815 So ganz ist mir nicht klar was Du willst, aber wäre `rpartition()` auf den gesamten Dateiinhalt eventuell das was Du suchst?
Ungetestet:
-
neuernutzer Die `kgv()`-Funktion hat eine schlechte API. Von so einer Funktion würde man erwarten, dass sie das KGV von gegebenen Zahlen ausrechnet, wenn sie allgemein benutzbar sein soll. Dazu müsste man dann die Zahlen aber noch mal einzeln in Sequenzen verpacken, *und* auch noch die 0 als Index angeben, damit die Funktion dann die einzelnen Zahlen wieder aus den eigentlich unsinnigen zusätzlichen Sequenzen zu holen. Das das eine Liste mit Listen bei Dir ist, ist ja schon nicht mehr der allgemeine Fall, sondern eine Besonderheit von *Deinen* Daten.
Einerseits gibt keinen Code der ”intuitiv” lesbar ist, man braucht immer Vorwissen, auf der anderen Seite sollten Mathematiker mit Funktionen höherer Ordnung kein Problem haben. `map()`, `filter()`, und `reduce()` sind die Grundlage von so ziemlich allen funktionalen Programmiersprachen, die ja deutlich näher an ”der Mathematik” dran sind, als prozedurale Sprachen. Die Funktionen heissen nicht immer genau so, aber diese drei Grundoperationen gibt es immer.
Wenn Effizienz keine Rolle spielt, kann man auch einfach nur `math.lcm()` und einen Generatorausdruck als Einzeiler verwenden:
Die `ausduennen()`-Funktion hat auch eine schlechte API. Erstens ist dieser Indexkram unnötig flexibel. Das macht das einfach nur komplizierter und schwerer zu verstehen als notwendig ohne das man wirklich etwas gewonnen hat. Dann hat die Funktion ein Argument das entscheidet welches von *drei* total unterschiedliche Rückgabewerten zurückgegeben wird. Es ist dann schwer nachzuvollziehen was denn bei einem Aufruf denn nun konkret zurückgegeben wird, denn beim Aufruf kann dieses Argument ja auch wieder eine Variable sein, wo man erst einmal schauen muss wie die zustande kommt. Das dieses Argument entweder die Zahl 0 oder der Buchstabe "v" oder *irgend etwas anderes* sein kann, ist vollkommen willkürlich und nicht nachvollziehbar.