Seite 4 von 5

Re: Python 'Benzingespräche'

Verfasst: Donnerstag 9. Dezember 2021, 21:31
von ulipy
narpfel hat geschrieben: Donnerstag 9. Dezember 2021, 21:23 @ulipy: Ich bin mir sicher, dass du deine Funktion nie mit null Argumenten getestet hast, aber (fehlerhaften) Code geschrieben hast, der das behandeln soll. Dass dir das nicht aufgefallen ist, zeigt, dass der Code zu komplex ist. Insbesondere auch, weil die Prüfung komplett überflüssig wäre, wenn du den Code auf zwei Funktionen aufgeteilt hättest.
Absolut einverstanden - danke!
Es fand bisher kein nennenswertes Testen statt und ich war und bin absolut nicht der Ansicht, dass der Code - so wie er gerade ist - bereits zuverlässig verwendbar wäre.

Im Gegenteil - es war klar, dass das rein logische Nachvollziehen hier nicht ausreichernd ist, genau wegen dieser Struktur..

Re: Python 'Benzingespräche'

Verfasst: Donnerstag 9. Dezember 2021, 21:34
von ulipy
Nachtrag: ich gehe aber davon aus, dass der Programmierer rasch etwas bemerken würde, falls er sich so etwas einfallen ließe...

Re: Python 'Benzingespräche'

Verfasst: Donnerstag 9. Dezember 2021, 22:01
von ulipy
@ulipy: Ich bin mir sicher, dass du deine Funktion nie mit null Argumenten getestet hast, aber (fehlerhaften) Code geschrieben hast, der das behandeln soll. Dass dir das nicht aufgefallen ist, zeigt, dass der Code zu komplex ist. Insbesondere auch, weil die Prüfung komplett überflüssig wäre, wenn du den Code auf zwei Funktionen aufgeteilt hättest.
Jetzt muss ich doch sofort nachfragen - das ist erst mal sehr überraschend:
Weshalb genau ergibt dies einen Laufzeitfehler - ein solcher is ja deutlich unwillkommener als eine Parser-Meldung...

Mit
if 1 < len(args) > 3 or len(args) == 0:
passiert das nicht mehr :o

Re: Python 'Benzingespräche'

Verfasst: Donnerstag 9. Dezember 2021, 22:06
von __deets__
Mit positions Argumenten hätte man lesbare Namen, und sowas passiert erst recht nicht, weil der Interpreter einen warnt. Ohne das man das vergessen kann & den Code mit solchen statements versalzt.

Re: Python 'Benzingespräche'

Verfasst: Donnerstag 9. Dezember 2021, 22:19
von narpfel
@ulipy: Für welche Zahlen `x` gilt denn `1 < x > 3`?

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 17:56
von ulipy
@all
in dem für mich als crash-Seitenensteiger extrem "dichten Wald" "Python" war ich in Sachen if-Struktur auch noch betriebsblind geworden :shock:

[ironie an]
Hätte mir doch jemand erklärt, dass "man" eine read-only Abfrage auch in einen bereits vorhandenen read-only block mit reinnimmt, aber nein...
[ironie aus]

Wurde dann heute beim Lesen von viewtopic.php?f=1&t=53600 wenigstens etwas getröstet - ich bin nicht alleine :wink: (wobei dies thematisch mit dem vorliegenden nichts bis wenig zu tun hat, mir jedoch sehr bekannt vorkommt...)

Vielleicht ist das hier unten ein besserer Weg, um erst daran anschliessend ggfs. auftauchende Umsetzungs-Schwierigkeiten klären zu können?

Die Erstellung eines doc-strings vor dem Umsetzen hätte ganz klar viele Vorteile - zumindest für mich persönlich (bin da ja aus Erfahrung nun durchaus deutlich vorsichtiger geworden..)
Beim ursprünglichen Wunsch, eine kleine Hilfe für den reinen Eigenbedarf zu erstellen, kam diese Ebene - wie fast immer, denke ich - definitiv zu kurz :!:

Meint ihr, so was macht Sinn?

Code: Alles auswählen

# Meta-Bemerkungen (in deutscher Sprache) entfallen ab dem pre-release.
# Sie dienen bis dahin ausschließlich Kommentaren, welche zum leichteren Verständnis des aktuellen Code-Status dienen

# !access settings via this function only please!
def settings(mode, keywrd, value):
    """
    Requires:
      # hier stehen momentan nur zwei Platzhalter
      environement(...)
      custom_error_handling(...)

    At program start, data_dict is loaded either 
    from default_dict or from a settings-file
    
    Arguments use:

      mode                  keywrd        value
      ----                  ------        -----
      'read_default_data'   None          None
        return: data_dict

      'save_settings_dict'  None          None
        return: data_dict

      'get_keyval'          dict-key      None
        return: value

      'update_keyval'       dict-key      value
        return: value

    Access samples:
      settings('read_default_data', None, None)
      settings('save_settings_dict', None, None)
      settings('get_keyval', key, None)
      settings('update_value', key, value)
    """
Falls ja, könnte zuerst die Logik im doc-string abgeklopft werden?

Zumindest kann ich mir das vorstellen.

Die Umsetzung könnte dann bei Bedarf am Ende dessen stehen.

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 18:37
von Sirius3
Dass jetzt kein *args mehr benutzt wird, ist definitiv besser. Trotzdem, statt eine Funktion zu schreiben, die über ihr erstes Argument vier verschieden Dinge macht, ist es immer noch besser vier Funktionen zu schreiben.
Das `Requires` ist unnötig, oder hast Du das schon jemals in einem Doc-String gelesen? Der Entwickler der Funktion muß ja sicherstellen, dass alle Abhängigkeiten vorhanden sind, das interessiert den Nutzer nicht die Bohne.

Und was zum Henker hast Du Dir dabei gedacht, bei keywrd das o wegzulassen? Wir sind nicht bei Glücksrad, wo man Vokale extra kaufen muß.

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 18:50
von ulipy
@narpfel
so wie du fragst, ist mit Sicherheit der Wurm drin - der Test 1 < len(args) > 3 war auf genehmigte 1 bis 3 Argumente angelegt (falsch natürlich wegen der 1, hätte 0 sein sollen...)

@Sirius3
Klare Ansage!
- Sparen ist nicht immer richtig - war absolut unnötig
- das mit der einen Funktion ist "eigen"

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 18:58
von narpfel
@ulipy: Wie ist es denn mit 0 statt 1 richtiger?

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 19:56
von ulipy
@narpfel
war nicht das wesentliche Problem zu dieser Zeit - weshalb sagst du mir nicht einfach, wie die korrekte Syntax wäre?

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 20:01
von ulipy
@Sirius3
Hmmm.. - den Docstring hatte ich bisher ausschließlich als für den Entwickler gedacht gesehen - nciht für den Anwendere des Programms. Verhält sich dies üblicherweise anders?

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 20:08
von pillmuncher
@ulipy: Die Syntax ist richtig, aber die Bedingung ist falsch. Das hier:

Code: Alles auswählen

1 < len(args) > 3
bedeutet dasselbe wie

Code: Alles auswählen

1 < len(args) and len(args) > 3
und damit dasselbe wie

Code: Alles auswählen

1 < len(args) and 3 < len(args)
Die Bedingung ist also bereits erfüllt, wenn len(args) größer ist als 3. Der Test darauf, ob len(args) größer ist als 1, ist folglich redundant, weil alles, was größer ist als 3 automatisch auch größer ist als 1.

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 20:09
von Sirius3
@ulipy: die Dokumentation enthält normalerweise keine Implementierungsdetails. Die muß der Anwender der Funktion nicht kennen.

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 20:24
von ulipy
pillmuncher hat geschrieben: Samstag 11. Dezember 2021, 20:08 @ulipy: Die Syntax ist richtig, aber die Bedingung ist falsch.
...
Danke dir, schau mir das genauer an!

@Sirius3
oh mei - wann würde denn der Docstring für einen Anwender relevant? Die Idee war ja genau die, ihn nur sehr begrenzt mit eher technischen Details zu konfrontieren -- auch noch auf englisch .
Dachte bis jetzt, der Anwender kommt nicht in den Kontakt mit Docstrings?

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 20:31
von pillmuncher
@ulipy: Der Anwender einer Bibliotheksfunktion ist der Programmierer, der diese Bibliotheksfunktion verwendet. Der Docstring ist für diesen Programmierer gedacht.

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 20:42
von ulipy
ok, dann habe ich das jetzt so verstanden:
der Anwender (Programmierer) muss in der Regel keine Implementierungsdetails aus dem docstring entnehmen können - stimmt das denn dann so?
Die Abgrenzung wäre damit natürlich Ermessensfrage

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 20:45
von ulipy
schaue jetzt erst mal im PEP 257 nach - komme dann evtl. zurück...

Re: Python 'Benzingespräche'

Verfasst: Samstag 11. Dezember 2021, 21:49
von ulipy
@pillmuncher, @narpfel
Nach einem "Klassenbesten" in Mathe es ist eine (fast) erschreckende Selbsterkenntnis, eine schlichte logische Bedingung dermaßen "falsch" zu formulieren.
Es sind die knapp dreißig Jahre, in denen dieser "trait" nicht bewusst und diszipliniert genutzt wurde, die solche Aberrationen erlauben...

Für meinen Teil ist das hier erst mal durch - ich stell nach den Anpassungen die ganze Funktion nochmals rein.

Danke!

Re: Python 'Benzingespräche'

Verfasst: Sonntag 12. Dezember 2021, 22:15
von ulipy
@all

Hab jetzt versucht, so eigentlich alles bisher Gesagte zu berücksichtigen - außer der gewollt beibehaltenen "Eigenheit" der Bedeutung des nun "task" genannten ersten args.

Bin inzwischen wirklich müde mit den "settings" - aber leider hilft das nicht weiter... es sollen ja die wichtlgsten Aspekte pythonischen (einfachen) Codes berücksichtigt sein, damit diese dann auch in kommenden Modulen angewandt werden können.

Wenn's "zerrissen" werden muss, dann muss das eben so sein...

Code: Alles auswählen

### B I T T E  V O R S I C H T ###
# Es könnte zu Testzwecken eine Testdatei in das
# Arbeitsverzeichnis geschrieben werden!
# Der Dateiname ist jedoch so gewählt, dass ein
# Konflikt zu unser aller Lebzeiten - auch in Summe -
# eher nicht vorkommen kann. :-)

# Meta-Bemerkungen (in deutscher Sprache):
#  Diese entfallen ab dem pre-release
#  Sie dienen bis dahin ausschließlich Kommentaren,
#  welche dem leichteren Verständnis des aktuellen
#  Code-Status während der Entwicklung dienen

# Laufzeitumgebung (Planungsgrundlage):
#   Win10, Python3
#   Umgebungsvariablen wie z. B. Installationsverzeichnis,
#   Zugriffsrechte etc. werden an anderem Ort überprüft

# BS-Unabhängigkeit:
#   Betriebssystem-Unabhängigkeit hat ! Erste Priorität !
#   (Sofern für das aktuelle target-System begründet
#   keine alternativen, proprietären Optionen vorzuziehen sind

import os
import json

# define customError class to intercept possible
# errors during coding of the APP
class customError(Exception):
    pass

# !access settings dictionary via this function only please!
def settings(task, keyword, value):
    u"""
    Read write settings data.
    
    At program start, settings_data is loaded either 
    from DEFAULT_SETTINGS or from data_path (settings-file).
    
    The arguments use is self-explanatory:

      task                  keyword        value
      ----                  ------        -----
      'read_default_data'   None          None
        return: settings_data

      'save_settings_data'  None          None
        return: settings_data

      'get_keyval'          dict-key      None
        return: value

      'update_keyval'       dict-key      value
        return: value

    Access samples:
      settings('read_default_data', None, None)
      settings('save_settings_data', None, None)
      settings('get_keyval', key, None)
      settings('update_keyval', key, value)

      # raise a customError:
      settings('read_default_data', None, 'any item except "None"')
    """

    ERR_MSG_ARG   = 'An arg != None was encountered unexpectedly'
    ERR_MSG_ARGS  = 'The type of at least one of two arguments was detected to be != None'
    ERR_MSG_TYPE  = 'Arg one unexpectedly was not of type string'
    ERR_MSG_TASK  = 'Arg one was not interpretable'

    # Arbeitsverzeichnis und Dateiname ist temporär !!!
    data_path = '.\\dummy_f_dfg_ff__Y_TmP_mydata.json'

    # defaults for settings data
    DEFAULT_SETTINGS = {
      '_del_orphaned':    False,  # if true:  del orphaned versions
      '_demo_only':       False,  # if true:  demo only
      '_hide_versions':   False,  # if true:  hide
      '_symlinks_dirs':   False,  # if false: ignore
      '_symlinks_files':  False,  # if false: ignore
      # 'scan_all_subdirs', # visibility of subdirs for power-user
    }

    # load settings_data
    if not os.path.exists(data_path):
        settings_data = DEFAULT_SETTINGS
    else:
        with open(data_path, 'r') as f:
            settings_data = json.load(f)    

    # get DEFAULT_SETTINGS
    if task == 'read_default_data':
        if keyword != None or value != None:
            raise customError(ERR_MSG_ARGS)
            quit()

        return DEFAULT_SETTINGS

    # save settings to disc
    elif task == 'save_settings_data':
        if keyword != None or value != None:
            raise customError(ERR_MSG_ARGS)
            quit()

        with open(data_path, 'w') as f:
           json.dump(settings_data, f)

        return settings_data

    # get a settings value
    elif task == 'get_keyval':
        # if not type(value) == str:
            # raise customError(ERR_MSG_TYPE)
            # quit()

        return settings_data[keyword]

    # update a dict value and save it
    elif task == 'update_keyval':
        # if not type(value) == str:
            # raise customError(ERR_MSG_TYPE)
            # quit()

        settings_data['keyword'] = value
        with open(data_path, 'w') as f:
           json.dump(settings_data, f)

        return settings_data[keyword]

    else:
        raise customError(ERR_MSG_TASK)
        quit()

print("settings('read_default_data', None, None)")
print(settings('read_default_data', None, None))
print()

print("settings('save_settings_data', None, None)")
settings('save_settings_data', None, None)

settings('get_keyval', '_hide_versions', None)
print("settings('get_keyval', '_hide_versions', None)")

settings('update_keyval', '_hide_versions', True)
print("settings('update_keyval', '_hide_versions', True)")

# raise a customError:
# print("settings('read_default_data', None, 'any item except None'")
# print(settings('read_default_data', None, 'any item except None'))
Das oben Stehende läuft wenigstens ohne Fehlermelduung durch - so weit ist das dann getestet...

Re: Python 'Benzingespräche'

Verfasst: Montag 13. Dezember 2021, 01:37
von snafu
Total intuitiv, diese festgelegten Strings und das doppelte None. Richtig pythonisch und bestimmt auch sehr leicht zu debuggen, wenn irgendwo ein Buchstabe verdreht oder vergessen wurde. 😍