TL; DR:必须为每个属性定义一组唯一的getter和setter()'d变量很糟糕.我可以定义通用的getter和setter,并将它们与我想要的任何变量一起使用吗?
假设我用一些不错的getter和setter创建了一个类:
class Foo
def getter(self):
return _bar+' sasquatch'
def setter(self, value):
_bar = value+' unicorns'
bar = property(getter, setter)
Run Code Online (Sandbox Code Playgroud)
太好了,对吧?
现在让我们说我放入另一个名为"baz"的变量,我不希望它被这个sasquatch/unicorn乐趣所遗漏.好吧,我想我可以制作另一组getter和setter:
class Foo
def bar_getter(self):
return _bar+' sasquatch'
def bar_setter(self, value):
_bar = value+' unicorns'
bar = property(bar_getter, bar_setter)
def baz_getter(self):
return _baz+' sasquatch'
def baz_setter(self, value):
_baz = value+' unicorns'
baz = property(baz_getter, baz_setter)
Run Code Online (Sandbox Code Playgroud)
但那不是很干,而且不必要地混乱了我的代码.我想我可以做一点DRYer:
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)
Run Code Online (Sandbox Code Playgroud)
虽然这可能会使我的代码DRYer,但它并不理想.如果我想unicornify和sasquatchify两个更多的变量,我将不得不添加另外四个函数!
必须有更好的方法来做到这一点.我可以在多个变量中使用单个通用getter和/或setter吗?
Unicorn-less和sasquatch-less真实世界的实现: 我正在使用SQLAlchemy ORM,并希望在从数据库中存储和检索数据时转换一些数据.一些转换适用于多个变量,我不想让我的类与getter和setter混乱.
Dou*_*gal 12
怎么样:
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')
Run Code Online (Sandbox Code Playgroud)
更一般地说:
def sasquatchify(val):
return val + ' sasquatch'
def unicornify(val):
return val + ' unicorns'
def getset(name, getting, setting):
return property(lambda self: getting(getattr(self, name)),
lambda self, val: setattr(self, name, setting(val)))
class Foo(object):
bar = getset('_bar', sasquatchify, unicornify)
baz = getset('_baz', sasquatchify, unicornify)
Run Code Online (Sandbox Code Playgroud)
或者,只需要更多工作,就可以使用完整的描述符协议,如agf的答案中所述.
这是描述符协议 property所基于的目的:
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
Run Code Online (Sandbox Code Playgroud)
虽然property在工厂功能可能适用于您的玩具示例,但听起来您可能需要更多控制您的实际用例.
使用getattribute和setattr,您可以为过去和未来的所有属性定义它。
class Foo(object):
x = 3
def __getattribute__(self, attr):
return str(object.__getattribute__(self, attr)) + ' sasquatch'
def __setattr__(self, attr, value):
object.__setattr__(self, attr, str(value) + ' unicorn')
print Foo.x
f = Foo()
print f.x
f.y = 4
print f.y
Run Code Online (Sandbox Code Playgroud)
这打印:
3
3 sasquatch
4 unicorn sasquatch
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4400 次 |
| 最近记录: |