What would be the most pythonic way to make an attribute that can be used in a lambda? What would be the most pythonic way to make an attribute that can be used in a lambda? tkinter tkinter

What would be the most pythonic way to make an attribute that can be used in a lambda?


Use a closure to return a function to be used as a callback, and define each condition as a function (using lambda or def, your preference) instead of each setter as a function.

class Eggs(object):    def __init__(self):        self.spam = 'Monster'        def spam_condition(string = None):            return (string is not None) and (len(string) <= 32)        self.spam_setter = self.set('spam', 'Ouch', spam_condition)        spam_button.bind('<Enter>', self.spam_setter)        self.spam_setter(val='Horse')    def set(self, name, value, condition):        def setter(val):            if type(val) is not .... :  # fill this in with the TYPE of the event                value = val            if condition(value):                setattr(self, name, value)        return setter

Edit: Now you can call the setter, which will check the condition, from anywhere.

Edit 2: This way, the setter will check if it got an event, and if not, use the value it's passed. You could also use:

if not isinstance(val, ....) :  # fill this in with the CLASS of the event


I still suggest using a dict and calling it a day. Subclass it and override __setitem__ to do your data validation, then don't worry about getters:

#!/usr/bin/env pythonclass Egg(dict):    def __init__(self, *args, **kwargs):        super(Egg, self).__init__(*args, **kwargs)        self['spam'] = 'foo'        spam_button.bind('<Enter>', lambda: self.__setitem__('spam', 'Ouch'))    def __setitem__(self, key, value):        if key == 'spam':            if len(value) > 32:                raise ValueError('"%s" is longer than 32 characters')            return super(Egg, self).__setitem__(key, value)        raise KeyError(key)


The validation issue can be handled using a property:

class Egg(object):    @property    def spam(self):        return self._spam    @spam.setter    def spam(self, value):            if len(value) <= 32:            self._spam = value

Obviously, you can still use self._spam = 'spam '*10+'baked beans and spam' with impunity.

Use the builtin setattr:

lambda: setattr(self, 'spam', 'Ouch')

If you object to ..."spam"... and prefer just ...spam..., you can use methods of property:

lambda: self.__class__.spam.fset(self, 'Ouch')

or, since property is a descriptor:

lambda: type(self).spam.__set__(self, 'Ouch')

But the first version is preferred, I hope for obvious reasons.