我有一个有两个成员的类 - 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
答案 0 :(得分:1)
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__