Ich schreibe eine Klasse in Python zu ändern, für einige Einstellungen wich sieht wie folgt aus:Ist es möglich, eine Klasse mit einem Dekorateur
class _CanvasSettings:
def __init__(self, **kwargs):
super().__init__()
self._size_x = _int(kwargs, 'size_x', 320)
self._size_y = _int(kwargs, 'size_y', 240)
self._lock_ratio = _bool(kwargs'lock_ratio', True)
def get_size_x_var(self):
return self._size_x
def _get_size_x(self):
return self._size_x.get()
def _set_size_x(self, value):
self._size_x.set(value)
size_x = property(_get_size_x, _set_size_x)
def get_size_y_var(self):
return self._size_y
def _get_size_y(self):
return self._size_y.get()
def _set_size_y(self, value):
self._size_y.set(value)
size_y = property(_get_size_y, _set_size_y)
def get_lock_ratio_var(self):
return self._lock_ratio
def _get_lock_ratio(self):
return self._lock_ratio.get()
def _set_lock_ratio(self, value):
self._lock_ratio.set(value)
lock_ratio = property(_get_lock_ratio, _set_lock_ratio)
wie Sie ich den Block hinzufügen sehen:
def get_something_var(self):
return self._something
def _get_something(self):
return self._something.get()
def _set_something(self, value):
self._something.set(value)
something = property(_get_something, _set_something)
Für jede einzelne Einstellung.
Ist es möglich, diese Aufgabe mit einem decorator
zu automatisieren?
würde Ich mag es, wie diese (Pseudo-Code) tun:
def my_settings_class(cls):
result = cls
for field in cls:
result.add_getter_setter_and_property(field)
return result
@my_settings_class
class _CanvasSettings:
def __init__(self, **kwargs):
super().__init__()
self._size_x = _int(kwargs, 'size_x', 320)
self._size_y = _int(kwargs, 'size_y', 240)
self._lock_ratio = _bool(kwargs'lock_ratio', True)
# Done !
Ist das möglich?
Wenn ja, wie?
Wie implementiert man die add_getter_setter_and_property()
Methode?
Edit:
Es gibt eine ziemlich ähnliche Frage hier ist: Es Python Class Decorator
aus den Antworten, die ich vermute, dass es möglich ist, etwas zu achive wie ich gebeten haben, aber können Sie mir einen Hinweis geben auf Wie könnte ich die add_getter_setter_and_property()
Funktion/Methode implementieren?
Anmerkung:
die _int()
, _bool()
Funktionen geben nur einen tkinter Int/Bool-var eighter von dem kwargs wenn die Zeichenfolge (fe 'size_x') vorhanden ist oder von dem Standardwert (fe 320) .
Meine Endlösung: Ich glaube, ich eine ziemlich gute Lösung gefunden haben. Ich habe einen Namen Einstellungen nur einmal hinzufügen, was imo genial :-) ist
import tkinter as tk
def _add_var_getter_property(cls, attr):
""" this function is used in the settings_class decorator to add a
getter for the tk-stringvar and a read/write property to the class.
cls: is the class where the attributes are added.
attr: is the name of the property and for the get_XYZ_var() method.
"""
field = '_' + attr
setattr(cls, 'get_{}_var'.format(attr), lambda self: getattr(self, field))
setattr(cls, attr,
property(lambda self: getattr(self, field).get(),
lambda self, value: getattr(self, field).set(value)))
def settings_class(cls):
""" this is the decorator function for SettingsBase subclasses.
it adds getters for the tk-stringvars and properties. it reads the
names described in the class-variable _SETTINGS.
"""
for name in cls._SETTINGS:
_add_var_getter_property(cls, name)
return cls
class SettingsBase:
""" this is the base class for a settings class. it automatically
adds fields to the class described in the class variable _SETTINGS.
when you subclass SettingsBase you should overwrite _SETTINGS.
a minimal example could look like this:
@settings_class
class MySettings(SettingsBase):
_SETTINGS = {
'x': 42,
'y': 23}
this would result in a class with a _x tk-intvar and a _y tk-doublevar
field with the getters get_x_var() and get_y_var() and the properties
x and y.
"""
_SETTINGS = {}
def __init__(self, **kwargs):
""" creates the fields described in _SETTINGS and initialize
eighter from the kwargs or from the default values
"""
super().__init__()
fields = self._SETTINGS.copy()
if kwargs:
for key in kwargs:
if key in fields:
typ = type(fields[key])
fields[key] = typ(kwargs[key])
else:
raise KeyError(key)
for key in fields:
value = fields[key]
typ = type(value)
name = '_' + key
if typ is int:
var = tk.IntVar()
elif typ is str:
var = tk.StringVar()
elif typ is bool:
var = tk.BooleanVar()
elif typ is float:
var = tk.DoubleVar()
else:
raise TypeError(typ)
var.set(value)
setattr(self, name, var)
nach, dass meine Einstellungen Klassen einfach aussehen:
@settings_class
class _CanvasSettings(SettingsBase):
_SETTINGS = {
'size_x': 320,
'size_y': 240,
'lock_ratio': True
}
Mögliche Duplikate von [Python Class Decorator] (http://stackoverflow.com/questions/681953/python-class-decorator) – ppperry
@ppperry Teile meiner Frage ist ziemlich ähnlich (danke für den Link!), Aber tun Sie (oder jemand anders) könnte mir einen Hinweis geben, wie ich die 'add_gett_setter_and_property' Methode/Funktion implementieren könnte? – linluk
Verwenden Sie die Funktion 'dir '. – ppperry