Python:用于设置对象值的变量名的方法

时间:2014-04-25 21:13:28

标签: python class variables object methods

让我们有一个简单的类,其中包含值和方法来设置它们:

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)函数合并为一,这是如何发生的,如果没有导入库就可以轻松完成?

4 个答案:

答案 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”的方法,可以在

中找到更多信息

https://docs.python.org/2/library/functions.html#property

答案 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类的骨架写为文本文件。我有这些类型的脚本,它们基于原始模块概述了我的单元测试用例。或者在文本编辑器中有一个脚本宏。代码的读取次数比写入的次数多很多次,因此不要只是为了节省一些按键来制作复杂的代码。