让我们有一个简单的类,其中包含值和方法来设置它们:
class Object:
def __init__(self, id):
self.__id = id
self.__value1 = None
self.__value2 = None
... etc
def set_value1(self, value1):
self.__value1 = value1
def set_value2(self, value2):
self.__value2 = value2
... etc
我可以以某种方式将这些.set_valueX(valueX)函数合并为一,这是如何发生的,如果没有导入库就可以轻松完成?
答案 0 :(得分:0)
可以使用setatter:
完成class obj(object):
def __setter(self,**kwargs):
key,value = kwargs.items()[0]
setattr(self,"__"+key,value)
def __init__(self,id):
self.id = id
self.__value1 = None
self.__value2 = None
#You should assign setter as the set funciton like this:
self.set_value1 = self.__setter
self.set_value2= self.__setter
#and so on...
使用相同的技术可以缩短 init 方法。
答案 1 :(得分:0)
如果您愿意妥协并使用一个处理所有设置器逻辑的函数,您可以
class Test:
def __init__(self):
self._value1 = 1
self._value2 = 2
self._value3 = 3
def set_value(self, attr, value):
setattr(x, attr, value)
并通过
访问每个方法设置器test_obj = Test()
test_obj.set_value("_value1", 10)
但是,我不建议采用任何一种方法。相反,您可能希望通过@property装饰器使用getter和setter。
这是一种更“Pythonic”的方法,可以在
中找到更多信息答案 2 :(得分:0)
我将在答案中说明,吸气剂和制定者不是非常pythonic,在这种情况下似乎是不必要的。如果您需要自定义get / set行为,请考虑使用属性(Python @property versus getters and setters),否则没有理由不以典型方式获取和设置(obj.foo = 'bar'
,x = obj.foo
)。
但我想如果你真的想......一点__getattr__
魔法可以做到:
class A(object):
def __init__(self, id):
self.__id = id
self.__value1 = None
self.__value2 = None
def _setter(self, name):
def set(value):
setattr(self, name, value)
return set
def __getattr__(self, name):
if name.startswith('set_'):
varname = name.split('_', 1)[-1]
return self._setter('__' + varname)
return super(A, self).__getattr__(name)
允许......
In [1]: a = A('123')
In [2]: a.set_value1(5)
In [3]: a.__value1
Out[3]: 5
In [4]: a.set_value2(7)
In [5]: a.__value2
Out[5]: 7
答案 3 :(得分:0)
这很简单,但要知道你为什么要这么做会有很多帮助。最Pythonic的方法可能是创建一个创建所有访问函数的元类。如果你试图做到这一点,我会查找python property
范例。但是,如果所有访问器功能都相同,为什么还需要单独的功能呢?您可以通过以下方式轻松设置值:
x = Object()
x.value = value
...只要你免除完全不必要的双下划线,至少。如果您确实需要更改每个属性的每个调用,则可以覆盖__setattr__
(Python Data Model Reference)。作为旁注,在我曾经合作的每个小组中,都非常不鼓励使用__变量方法。它并没有阻止任何人实际访问该值(你可以通过instance._Object__value1
进行访问),但这会使子类化变得非常糟糕。
如果您想对每个属性获取或设置进行相同的预处理,您可以始终执行以下操作:
class Object:
_ATTR_NAMES = ('value1', 'value2', ...)
def __init__(self):
for name in self._ATTR_NAMES:
setattr(self, "_" + name, None)
def set_attr(self, name, value):
if name in self._ATTR_NAMES:
setattr(self, name[1:], value)
else:
raise AttributeError("No attribute named %s found"%name)
Python的setattr是一个在属性上设置具有给定名称的属性的函数。在这种情况下,您可以简单地拥有一个属性列表,根据该属性设置它们,并使用相应的“getattr”来检索它们。功能。尽管如此,我对你这样做的原因持谨慎态度。通常显式优于隐式。很难只做一个额外的获取/设置功能,使参考更加清晰。
如果你真的必须,你也可以使用非常类似于我刚刚展示的属性的技术生成get / set函数(即,动态创建包裹set_attr
的函数),但同样,它通常使代码更难维护和阅读。除非你真的有强烈而明确的需要,否则我会避免使用这些技术。如果你真的必须这样做,这样的事情会起作用:
class Object:
_ATTR_NAMES = ('value1', 'value2', ...)
def __init__(self):
for name in self._ATTR_NAMES:
setattr(self, "_" + name, None)
def _set_attr(self, name, value):
if name in self._ATTR_NAMES:
setattr(self, name[1:], value)
else:
raise AttributeError("No attribute named %s found"%name)
# This binds named set functions to the class
for name in Object._ATTR_NAMES:
def tempSetter(self, value):
self._set_attr(name, value)
setattr('set_'+name, tempSetter)
del name
del tempSetter
这是一种做法的黑客方式。在元类中进行这种处理更为优雅。但是,由于需要了解大量背景知识,我将跳过这一点。如果您需要在每个集合函数之前进行预处理,通常更喜欢按照以下方式执行:
def _preprocessing(self, value):
# Do something here
return value
def set_value1(self, value):
value = self._preprocessing(value)
self._value1 = value
def set_value2(self, value):
value = self._preprocessing(value)
self._value2 = value
最后,如果你担心的是生成样板获取/设置函数的时间,那么只需编写一个脚本,将Python类的骨架写为文本文件。我有这些类型的脚本,它们基于原始模块概述了我的单元测试用例。或者在文本编辑器中有一个脚本宏。代码的读取次数比写入的次数多很多次,因此不要只是为了节省一些按键来制作复杂的代码。