Python - 如何根据名称重置类成员

时间:2016-05-03 22:38:25

标签: python-2.7

我有一个有两个成员的类 - m1是一个字符串,m2是一个字典。

我想通过调用myA.m2.reset()等同于self.m2.clear();来重置m2。并通过调用myA.m1.reset()等效于self.m1 = None来重置m1。

那么如何在A类中实现这种重置方法?

class A(object):
    def __init__(self):
        self.m1 = None
        self.m2 = {}

    def reset(self):
        """
         if it is m2: self.m2.clear()
         elif it is m1: self.m1 = None
        """

myA = A()
myA.m2[1] = 2

3 个答案:

答案 0 :(得分:1)

编辑:OP我很抱歉 - 我建议使用描述符似乎是一个好主意,但它不会让你以强大的方式编写像myA.m2.reset()这样的代码。

我会在这里保留这个答案以供参考,以防它给你任何想法。

这是python descriptors的工作!

如果我理解,你希望能够做到这样的事情:

myA.some_member.reset()

...并且根据成员的“类型”(我松散地使用该词)具有自定义行为。对于类似dict的m2成员,你可以正常工作:

class ResettableDict(dict):
    def reset(self):
        self.clear()

class A(object):
    def __init__(self):
    self.m2 = ResettableDict()

但是,您要遇到的问题是,您不能通过子类str来做类似的事情,因为字符串是不可变的(即,它们不能像{{1}那样被“清除” })。此外,当您使用赋值运算符为dict成员提供某些值时,它将不再是ResettableString。例如:

ResettableString

测试:

class ResettableString(str):
    pass # Just a placeholder for this example

Python具有“重载”大多数运算符的能力。但是你不能写一个通常会重载>>> myA = A() >>> myA.m2[1] = 2 >>> type(myA.m2) <class '__main__.ResettableDict'> # works! >>> myA.m1 = 'string!' >>> type(myA.m2) <class 'str'> # no longer a ResettableString! DOH!!! (赋值)运算符的类。该怎么办?

答案:正如我在开头所说的,描述符!我们将创建一个名为=的描述符。 Resettable将使用Resettable方法将成员的值恢复为默认值。

你会像这样使用它:

reset()

以下是class A(object): m1 = Resettable('m1', None) m2 = Resettable('m2', {})

Resettable

Python描述符提供了许多功能。其中一个问题是class Resettable(object): '''A class descriptor that can be reset to its default value.''' def __init__(self, name, default): self.default = default def reset(self): setattr(self.current_instance, self.name, self.default) del self.current_instance def __get__(self, obj, typ): try: return getattr(obj, '_%s' % self.name) except AttributeError: setattr(obj, self.name, self.default) return self.default finally: self.current_instance = obj def __set__(self, obj, value): setattr(obj, '_%s' % self.name, value) (赋值)运算符的“重载”(通过=方法;提供此方法是optoinal),以及__set__(“get”)运算符(通过.方法)。

现在,当您为对象成员分配值时,描述符对象提供的行为将覆盖默认的Python get和set行为。

__get__

答案 1 :(得分:0)

m1和m2是类的成员而不是它的实例。类的成员不能调用其包含类的函数,成员只能调用其实例中的函数。在sinpler上下文中,m1不应该调用myA.reset()。我很确定你可以调用myA.m1.clear()。如果你想重置它,你可以传递一个参数告诉类要清除哪个变量。

答案 2 :(得分:0)

这并不像我希望的那样优雅,基于描述符的解决方案(我在其他答案中放弃了),但我认为这就是我想要的。

change

测试:

class Resettable(object):
    '''A class with "resettable" fields.'''
    _resettables = {}
    def __init__(self):
        for field, value in self._resettables.items():
            setattr(self, field, value)
    def reset(self, field):
        try:
            setattr(self, field, self._resettables[field])
        except KeyError:
            raise AttributeError('%s is not a resettable field' % field)

class A(Resettable):
    _resettables= dict(m1 = None, m2 = {})

您可以完全使用不同的方法,并使用>>> myA.m1 = 'string' >>> myA.reset('m1') >>> assert myA.m1 is None 方法返回默认值的任何字段值,而不是在reset方法中执行繁重的工作。

__getattr__