Python:通用的getter和setter

2024-10-01 07:12:34 发布

您现在位置:Python中文网/ 问答频道 /正文

TL;DR:必须为每个property()'d变量定义一组唯一的getter和setter集很糟糕。我可以定义通用的getter和setter并将它们用于我想要的任何变量吗?

假设我用一些漂亮的getter和setter来创建一个类:

class Foo
    def getter(self):
        return _bar+' sasquatch'

    def setter(self, value):
        _bar = value+' unicorns'

    bar = property(getter, setter)

很不错,对吧?在

现在让我们假设我加入了另一个名为“baz”的变量,我不想在这个sasqutch/unicorn的乐趣中忽略它。好吧,我想我可以再做一组吸气和二垒手:

^{pr2}$

但这不是很枯燥,而且不必要地扰乱了我的代码。我想我可以把它弄干一点:

class Foo
    def unicornify(self, value):
        return value+' unicorns'

    def sasquatchify(self, value):
        return value+' sasquatch'

    def bar_getter(self):
        return self.sasquatchify(_bar)

    def bar_setter(self, value):
        _bar = self.unicornify(_bar)

    bar = property(bar_getter, bar_setter)

    def baz_getter(self):
        return self.sasquatchify(_baz)

    def baz_setter(self, value):
        _baz = self.unicornify(_baz)

    baz = property(baz_getter, baz_setter)

虽然这可能会使我的代码干燥剂,但并不理想。如果我想把另外两个变量单独化和精确化,我必须再增加四个函数!在

一定有更好的办法。我可以在多个变量中使用一个通用的getter和/或setter吗?在

无独角兽和无sasquatch的实际实现:我正在使用SQLAlchemy ORM,希望在从数据库中存储和检索数据时转换一些数据。有些转换适用于多个变量,我不想在类中使用getter和setter。在


Tags: selfreturn定义foovaluedefbarproperty
3条回答

这就是descriptor protocolproperty基于的是:

class Sasicorn(object):                              
    def __init__(self, attr):                        
        self.attr = "_" + attr                       
    def __get__(self, obj, objtype):                 
        return getattr(obj, self.attr) + ' sasquatch'
    def __set__(self, obj, value):                   
        setattr(obj, self.attr, value + ' unicorns') 

class Foo(object):                                   
    def __init__(self, value = "bar"):               
        self.bar = value                             
        self.baz = "baz"                             
    bar = Sasicorn('bar')                            
    baz = Sasicorn('baz')                            

foo = Foo()                                          
foo2 = Foo('other')                                  
print foo.bar                                        
# prints bar unicorns sasquatch
print foo.baz                                        
# prints baz unicorns sasquatch
print foo2.bar                                       
# prints other unicorns sasquatch

虽然工厂函数中的property对于您的玩具示例来说可能还不错,但听起来您可能需要对实际用例进行更多的控制。在

我的一个同事建议使用闭包返回getter和setter函数,这也是我决定使用的。在

class Foo(object):
    def setter(var):
        def set(self, value):
            setattr(self, var, value+' unicorn')
        return set

    def getter(var):
        def get(self):
            return getattr(self, var)+' sasquatch'
        return get

    bar = property(getter('_bar'), setter('_bar'))

f = Foo()
f.foo = 'hi'
print f.foo

但感谢大家的回答:)

不如就:

def sasquatchicorn(name):
    return property(lambda self: getattr(self, name) + ' sasquatch',
                    lambda self, val: setattr(self, name, val + ' unicorns'))

class Foo(object):
    bar = sasquatchicorn('_bar')
    baz = sasquatchicorn('_baz')

一般来说:

^{pr2}$

或者,只需做更多的工作,就可以使用完整描述符协议,如agf's answer中所述。在

相关问题 更多 >