Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 创建可在lambda中使用的属性的最具Python风格的方法是什么?_Oop_Tkinter_Python - Fatal编程技术网

Oop 创建可在lambda中使用的属性的最具Python风格的方法是什么?

Oop 创建可在lambda中使用的属性的最具Python风格的方法是什么?,oop,tkinter,python,Oop,Tkinter,Python,更具体地说,我希望能够支持lambda:,但我希望代码清晰、简洁。我必须验证该值,因此我需要某种setter。我需要使用lambda,因为我需要将回调传递给Tkinter事件。我还需要能够在绑定外部修改属性的值 在我下面的示例中,假设一个名为spam\u button的按钮小部件已全局声明。另外,请确保类Eggs至少有10个属性,而不是所有属性都需要以相同的方式访问(我喜欢一致性) 第一种可能的方法是使用getter和setter: class Eggs(object): def __

更具体地说,我希望能够支持
lambda:
,但我希望代码清晰、简洁。我必须验证该值,因此我需要某种setter。我需要使用lambda,因为我需要将回调传递给Tkinter事件。我还需要能够在绑定外部修改属性的值

在我下面的示例中,假设一个名为
spam\u 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
类卵(对象):
定义初始化(自):
self._spam=“”
self.set_垃圾邮件(“怪物”)
打印self.get_spam()
spam_按钮.bind(“”,lambda:self.set_spam('Ouch'))
def set_垃圾邮件(自我,垃圾邮件):

如果len(spam)使用闭包返回要用作回调的函数,并将每个条件定义为函数(使用
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

我仍然建议使用dict并结束一天。将其子类化并覆盖
\uuuuu setitem\uuuuuu
以进行数据验证,然后不用担心getter:

#!/usr/bin/env python

class 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)
#/usr/bin/env python
蛋类(dict):
定义初始化(self,*args,**kwargs):
超级(鸡蛋,自我)。\uuuuuuuuuuuuuuuuuuuuuuuuu(*args,**kwargs)
self['spam']='foo'
spam_按钮.bind(“”,lambda:self._setitem__uu('spam','Ouch'))
定义设置项(自身、键、值):
如果键==“垃圾邮件”:
如果len(值)>32:
raise VALUERROR(“%s”超过32个字符)
返回super(Egg,self)。\uuuuu setitem\uuuuuuu(键,值)
升起钥匙错误(钥匙)

可以使用
属性处理验证问题

class Egg(object):
    @property
    def spam(self):
        return self._spam

    @spam.setter
    def spam(self, value):    
        if len(value) <= 32:
            self._spam = value
如果您反对
…“垃圾邮件”…
并且只喜欢
…垃圾邮件…
,您可以使用
属性的方法

lambda: self.__class__.spam.fset(self, 'Ouch')
或者,由于
属性
是一个描述符:

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

但出于明显的原因,我希望首选第一个版本。

我喜欢基于类的方法。您可能需要执行的验证集有限(例如字符串的最大长度、数字的有效范围等),因此类的数量有限

例如:

class LimitedLengthString(object):
    def __init__(self, max_length):
        self.max_length = max_length
    def set(self, value):
        if len(value) <= self.max_length:
            self.value = value
    def get(self):
        return value

class Eggs(object):
    def __init__(self):
        self.spam = LimitedLengthString(32)
        self.spam.set('Monster')
        print self.spam.get()
        spam_button.bind('<Enter>', lambda: self.spam.set('Ouch'))
class LimitedLengthString(对象):
定义初始长度(自身,最大长度):
self.max\u length=最大长度
def设置(自身,值):

if len(value)感谢这个想法,但我真的不想使用字符串来访问属性(我也可以使用字典),而且这没有提供一种在绑定之外设置和验证值的方法(除非每次我想设置值时都使用
self.set('spam','Ouch',spam_condition)(
),这真的很难看)。另外,您需要向
setter
函数添加
事件
参数,否则Tkinter无法传递事件(并获取
值错误
)。现在可以从任何位置使用setter。如果我使用
lambda e:self.spam\u setter()
作为回调,并从
setter
中删除
事件
参数,我不需要每次设置值时都指定
val=
。有没有可能在回调中从
lambda e:
中删除
e
呢?我更新了我的帖子,向您展示了如何在没有
lambda
或键入
val
的情况下通过检查setter接收到的变量来执行此操作。我将使用
*vals
而不是
val
作为参数,我将使用
isinstance
查找哪个arg是值(哪个是事件)。现在应该可以了。感谢您的帮助。他希望在设置垃圾邮件时自动检查条件,因此仅使用
setattr
没有帮助。为什么不实施描述符协议?()
class Egg(object):
    @property
    def spam(self):
        return self._spam

    @spam.setter
    def spam(self, value):    
        if len(value) <= 32:
            self._spam = value
lambda: setattr(self, 'spam', 'Ouch')
lambda: self.__class__.spam.fset(self, 'Ouch')
lambda: type(self).spam.__set__(self, 'Ouch')
class LimitedLengthString(object):
    def __init__(self, max_length):
        self.max_length = max_length
    def set(self, value):
        if len(value) <= self.max_length:
            self.value = value
    def get(self):
        return value

class Eggs(object):
    def __init__(self):
        self.spam = LimitedLengthString(32)
        self.spam.set('Monster')
        print self.spam.get()
        spam_button.bind('<Enter>', lambda: self.spam.set('Ouch'))
class LimitedLengthString(object):
    def __init__(self, name, max_length):
        self.name = name
        self.max_length = max_length

    def __set__(self, instance, value):
        if len(value) <= self.max_length:
            instance.__dict__[self.name] = value

    def __get__(self, instance, owner):
        return instance.__dict__[self.name]

class Eggs(object):
    spam = LimitedLengthString('spam', 32)
    def __init__(self):
        self.spam = 'Monster'
        print self.spam  # prints 'Monster'
        self.spam = 'x' * 40
        print self.spam  # still 'Monster'
        spam_button.bind('<Enter>', lambda: self.spam = 'Ouch')