D K*_*D K 5 python oop tkinter
更具体地说,我希望能够支持lambda: <some_or_other_setter>,但我希望保持代码清晰,简洁.我必须验证值,所以我需要一个某种类型的setter.我需要使用lambda,因为我需要将回调传递给Tkinter事件.我还需要能够修改绑定之外的属性值.
在我的以下示例中,假设spam_button已全局声明了一个名为的按钮窗口小部件.还假设该类Eggs将具有至少10个属性,而不是以相同的方式访问所有属性(我喜欢一致性).
我能做到的第一种可能的方法是使用getter和setter:
class Eggs(object):
def __init__(self):
self._spam = ''
self.set_spam('Monster')
print self.get_spam()
spam_button.bind('<Enter>', lambda: self.set_spam('Ouch'))
def set_spam(self, spam):
if len(spam) <= 32:
self._spam = spam
def get_spam(self):
return self._spam
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用此方法并具有许多属性,则代码可能会花费太长时间来管理.
我可以做的第二种方法是使用属性,并在回调中使用setter:
class Eggs(object):
def __init__(self):
self._spam = ''
self.spam = 'Monster'
print self.spam
spam_button.bind('<Enter>', lambda: self.set_spam('Ouch'))
def set_spam(self, spam):
if len(spam) <= 32:
self._spam = spam
def get_spam(self):
return self._spam
spam = property(get_spam, set_spam)
Run Code Online (Sandbox Code Playgroud)
直接访问属性时,这种方式比第一种方式简单,但在使用lambda时则不一致.
第三种方法是使用get和set方法创建一个额外的类:
class Spam(object):
def __init__(self):
self._value = ''
def set(self, value):
if len(spam) <= 32:
self._value = value
def get(self):
return self._value
class Eggs(object):
def __init__(self):
self._spam = ''
self.spam = Spam()
self.spam.set('Monster')
print self.spam.get()
spam_button.bind('<Enter>', lambda: self.spam.set('Ouch'))
Run Code Online (Sandbox Code Playgroud)
这个方法比第一个方法更有条理,但我需要为每种类型的验证创建一个类.
我可能做的最后一种方法是使用方法而不是属性(属性是第二个例子):
class Eggs(object):
def __init__(self):
self._spam = ''
self.spam('Monster')
print self.spam()
spam_button.bind('<Enter>', lambda: self.spam('Ouch'))
def spam(self, spam=None):
if spam != None:
if len(spam) <= 32:
self._spam = spam
else:
return self._spam
Run Code Online (Sandbox Code Playgroud)
这种方法可能是最短的,但是一目了然地告诉我是否正在进行或设置.
哪种(如果有的话)这些方法是首选的?
使用闭包返回一个用作回调的函数,并将每个条件定义为一个函数(使用lambda或def,您的偏好),而不是将每个setter定义为一个函数。
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
Run Code Online (Sandbox Code Playgroud)
编辑:现在您可以从任何地方调用设置器,它将检查条件。
编辑2:这样,setter 将检查它是否收到事件,如果没有,则使用它传递的值。您还可以使用:
if not isinstance(val, ....) : # fill this in with the CLASS of the event
Run Code Online (Sandbox Code Playgroud)