Options Splitting

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
Benutzeravatar
wuf
User
Beiträge: 1497
Registriert: Sonntag 8. Juni 2003, 09:50

Donnerstag 8. März 2018, 14:37

Hi Forum Freunde

Ich möchte die mit **kwargs übergebenen Optionen bei der Initialisieung der
Klasse MyOwnWidget in zwei Gruppen aufteilen. Die zwei Gruppen heissen
self.standard_options und self.specific_options.

Die Optionen bg und highlightthickness gehören zur Gruppe:
self.standard_options

Die Optionen horizontal_scroll, vertical_scroll gehören zur Gruppe:
self.specific_options

Ist es möglich das folgende Skript hierfür noch zu vereinfachen?:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk


class MyOwnWidget(object):
    SPECIFIC_OPTIONS = ('horizontal_scroll', 'vertical_scroll')
    
    def __init__(self, **kwargs):
        
        self.standard_options = dict()
        self.specific_options = dict()
         
        spec_options = [key for key in kwargs if key in self.SPECIFIC_OPTIONS]
        
        temp_dict = dict()
        for key in spec_options:
            temp_dict[key] = kwargs[key]
            del kwargs[key]
            
        self.standard_options.update(kwargs)
        self.specific_options.update(temp_dict)

        print('Standard Optionen:\n', self.standard_options)
        print()
        print('Specific Optionen:\n', self.specific_options)
        
app_win = tk.Tk()

my_own_widget = MyOwnWidget(bg=0, highlightthickness=0, vertical_scroll=True,
    horizontal_scroll=True)

app_win.mainloop()
Gruss wuf :wink:
Take it easy Mates!
Sirius3
User
Beiträge: 8805
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 8. März 2018, 15:08

@wuf: das ganze tk-Template wäre für die Frage eigentlich nicht nötig gewesen. Von daher würde ich solche allgemeinen Funktionen auch in einer Funktion schreiben. `update` ist ja nur nötig, wenn wirklich was geupdated wird, hier füllst Du aber nur ein leeres Wörterbuch.

Code: Alles auswählen

def split_dict(dict, keys):
    keys, dict_keys = set(keys), set(dict)
    this = {k: dict[k] for k in dict_keys & keys}
    others = {k: dict[k] for k in dict_keys - keys}
    return this, others
Benutzeravatar
wuf
User
Beiträge: 1497
Registriert: Sonntag 8. Juni 2003, 09:50

Donnerstag 8. März 2018, 19:30

@Sirius3: Besten Dank für deine Antwort. Deine Funktion erfüllt die Aufteilung der Optionen in die beiden Dictionaries. Habe dies mit folgendem Skript ausprobiert:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk


class MyOwnWidget(object):
    SPECIFIC_OPTIONS = ('horizontal_scroll', 'vertical_scroll')
    
    def __init__(self, **kwargs):
        
        
        self.specific_options, self.standard_options = self.split_dict(
            kwargs, self.SPECIFIC_OPTIONS)

        print('Standard Optionen:\n', self.standard_options)
        print()
        print('Specific Optionen:\n', self.specific_options)
        
 
    def split_dict(self, dict, keys):
        keys, dict_keys = set(keys), set(dict)
        this = {k: dict[k] for k in dict_keys & keys}
        others = {k: dict[k] for k in dict_keys - keys}
        return this, others
        
app_win = tk.Tk()

my_own_widget = MyOwnWidget(bg=0, highlightthickness=0, vertical_scroll=True,
    horizontal_scroll=True)

app_win.mainloop()
Sorry ich habe mich zu wenig genau ausgedrückt. Was ich eigentlich will ist eine eigene Tk-Widget-Klasse erstellen. Diese setzt sich aus einem Standard Tk-Widget z.B. Canvas und eigenen Erweiterungen zusammen. Darum die üppige Zugabe des tk-Templates. Die Optionen für meine Widget-Klasse setzen sich zusammen aus den Standard Tk-Optionen für das Canvas-Widget und eigenen Optionen. Für die Initialisierung der Klasse werden alle mit **kwargs übernommen. In meiner Klasse sind die beiden Wörterbücher standard_options und specific_options mit Vorgabeoptionen belegt. Bei einem einfachen Einsatz meiner Klasse genügen diese Vordefinierten Optionen. Erst beim Einsatz mit einer spezifischer Konfiguration werden zusätzliche Optionen übergeben. Dann muss ein update der beiden Wörterbücher erfolgen. Dabei darf das Wörterbuch standard_options nur Optionen enthalten, welche für das Canvas bestimmt sind und die Optionen für meine eigene Erweiterungen dürfen nur im Wörterbuch specific_options erscheinen. Darum müssen die Optionen, welche nicht für das Canvas bestimmt aus dem kwargs entfernt werden bevor damit das Wörterbuch standard_options updated wird.

Hier mein erweitertes Testskript:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk


class MyOwnWidget(tk.Canvas):
    SPECIFIC_OPTIONS = ('horizontal_scroll', 'vertical_scroll')
    
    def __init__(self, **kwargs):
        
        self.standard_options = {
            'bd'                : 0,
            'highlightthickness': 0
            }
            
        self.specific_options = {
            'horizontal_scroll' : False,
            'vertical_scroll'   : False
            }
         
        spec_options = [key for key in kwargs if key in self.SPECIFIC_OPTIONS]
        
        temp_dict = dict()
        for key in spec_options:
            temp_dict[key] = kwargs[key]
            del kwargs[key]
            
        self.standard_options.update(kwargs)
        self.specific_options.update(temp_dict)

        print('Standard Optionen:\n', self.standard_options)
        print()
        print('Specific Optionen:\n', self.specific_options)
        
        tk.Canvas.__init__(self, app_win, **self.standard_options)
        
        # My own options
        horzontal_scroll = self.specific_options['horizontal_scroll']
        vertical_scroll = self.specific_options['vertical_scroll']
        print('\nHorizontal Scroll:', horzontal_scroll)
        print('Verical Scroll   :', vertical_scroll)
        
app_win = tk.Tk()

my_own_widget = MyOwnWidget(bd=0, highlightthickness=0, bg='steelblue',
    vertical_scroll=True, horizontal_scroll=True)
my_own_widget.pack(fill='both', expand=True)

app_win.mainloop()
OK Sirius3 ich hoffe du verstehst auf was ich aus bin.
Gruss wuf :wink:
Take it easy Mates!
Sirius3
User
Beiträge: 8805
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 8. März 2018, 19:59

@wuf: ich verstehe schon, was Du willst, aber es ist immer gut, eine Funktion so allgemein zu schreiben, wie es geht, ohne dass es kompliziert wird. Deshalb ist es ungünstig, dass Du meine Funktion als Methode definiert hast, weil sie mit Deinem konkreten Problem nichts zu tun hat.

Wenn die Parameter mit ihren Defaultwerten klar sind, warum benutzt Du dann **kwargs?
Benutzeravatar
wuf
User
Beiträge: 1497
Registriert: Sonntag 8. Juni 2003, 09:50

Donnerstag 8. März 2018, 20:38

@Sirius3: Ich habe interessehalber einmal im Tk-Hauptmodul Tkinter.py herum geschnüffelt um zu sehen auf welche Art dort die diversen Widget-Klassen programmiert wurden. Das ganze ist ziemlich komplex. Da versucht man selber etwas welches übersichtlicher ist zu erstellen. Es ist natürlich schon so, dass manches auf verschieden Arten angegangen werden kann um eine Lösung zu finden. OK Sirius3 ich danke dir noch für deine Hilfe. Werde noch ein wenig weiter tüfteln.

Grüss wuf :wink:
Take it easy Mates!
Antworten