oop - 制作可在 lambda 中使用的属性的最 Pythonic 方式是什么?

标签 oop tkinter python

更具体地说,我希望能够支持 lambda: <some_or_other_setter> ,但我想保持代码清晰简洁。我必须验证这个值,所以我需要某种 setter。我需要使用 lambda 因为我需要将回调传递给 Tkinter 事件。我还需要能够修改绑定(bind)之外的属性值。

在下面的示例中,假设一个名为 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

但是如果我使用这种方法并且有很多属性,代码可能会变得太长而无法管理。

我可以做到这一点的第二种方法是使用属性,并在回调中使用 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)

这种方式在直接访问属性时比第一种方式简单一些,但是在使用 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'))

这种方法比第一种方法更有条理,但我需要为每种类型的验证创建一个类。

我可能做的最后一种方法是使用方法而不是属性(属性是第二个例子):
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

这种方法可能是最短的,但很难一目了然地判断我是在获取还是设置。

这些方法中的哪一种(如果有的话)是首选?

最佳答案

使用闭包返回一个用作回调的函数,并定义每个 条件 作为函数(使用 lambdadef ,您的偏好)而不是每个 二传手作为一个函数。

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

编辑:现在您可以从任何地方调用 setter ,它将检查条件。

编辑 2:这样,setter 将检查它是否收到事件,如果没有,则使用它传递的值。您还可以使用:
if not isinstance(val, ....) :  # fill this in with the CLASS of the event

关于oop - 制作可在 lambda 中使用的属性的最 Pythonic 方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6793958/

相关文章:

python - 查看python中所有继承的类

php - 调用未定义的方法 dbConnection::query() - 如何修复它?

python - 使用 Anaconda 在 Jupyter 笔记本中进行 Scikit Learn

python - typeerror参数 'image'必须为iplimage

python - Blender 更改了我的对象的名称

javascript - 使用 this 和 prototype 在 JavaScript 中定义类的方法有什么区别?

javascript - 如何在 JavaScript 中为 namespace 中的对象创建静态成员?

Python:如何在消息框中获取输入框?

Python Tkinter 绑定(bind)子部件

python - 如何使用 Tkinter 包几何管理器重叠小部件?