在python中是否有一种方法可以给出一个python类:
class Foo(object):
apple = None
orange = None
def __init__(self, apple=None, orange=None)
super(Foo, self).__init__()
self.apple = apple
self.orange = orange
换句话说:
orange is None | orange is not None
|
apple is None NO | YES
________________________________________|___________________________
|
apple is not None YES | NO
如何在python中执行此操作?
答案 0 :(得分:4)
在构造函数中,如果它们raise
或两者都设置,则ValueError
None
就足够简单了。问题稍后在代码中。
遵循最小惊喜的原则,我认为你应该将变量标记为私有并使用setter方法(不是属性设置器,普通旧方法)。这清楚地表明,当设置值时,您正在做额外的逻辑,并且如果需要,它会为您提供显而易见的添加额外逻辑的位置。但是,使用getter属性方法会很好。所以像这样:
class Foo(object):
def __init__(self, apple=None, orange=None):
super(Foo, self).__init__()
if apple is None and orange is None:
raise ValueError('apple and orange cannot both be None')
if apple is not None and orange is not None:
raise ValueError('apple and orange cannot both be set')
self._apple = apple
self._orange = orange
@property
def apple(self):
return self._apple
@property
def orange(self):
return self._orange
def setAppleClearOrange(self, value):
if value is None:
raise ValueError('Cannot set both to None')
self._orange = None
self._apple = value
def setOrangeClearApple(self, value):
if value is None:
raise ValueError('Cannot set both to None')
self._apple = None
self._orange = value
是的,它有点冗长,但显而易见你的意图是什么,实际上更重要。
答案 1 :(得分:1)
像
这样的东西if !((self.apple==None)^(self.orange==None))
// some error
可能做的诀窍...... ^是XOR运算符,如果操作数中的一个(但不是两个)都为真,则返回true。
答案 2 :(得分:0)
objs = filter(None, [apple, orange, ...])
if len(objs) == 0:
raise Exception("At least 1 object of [apple, orange] must be different from None.")
elif len(objs) > 1:
raise Exception("At most 1 object of [apple, orange] should be different from None.")
答案 3 :(得分:0)
您可以覆盖该类的__setattr__()
,并让它为您处理该逻辑。见http://docs.python.org/2/reference/datamodel.html#object.setattr
像
这样的东西class FooBar(object):
def __setattr__(self, key, val):
if key == 'apple' or key == 'orange':
# Decide what to do about it
self.__dict__[key] = val
请注意,您需要通过对象__dict__
访问密钥以避免无限循环,因为__setattr__()
会替换正常的分配机制。
另请注意,这将检查对这两个变量的每个分配,包括您自己的代码。如果那不是您想要的,那么就像其他人建议的那样在__init__()
中进行一些测试。
答案 4 :(得分:0)
如果需要,这是一个将另一个方面设置为None
的版本。如果它们都设置为None
class Foo(object):
def __init__(self, apple=None, orange=None):
# make sure exactly 1 of apple/orange is not None
if sum(x is None for x in (apple, orange)) != 1:
raise ...
self._apple = apple
self._orange = orange
@property
def apple(self):
return self._apple
@apple.setter
def apple(self, value):
if value is not None:
self._orange = None
elif self._orange is None:
raise ...
self._apple = value
@property
def orange(self):
return self._orange
@orange.setter
def orange(self, value):
if value is not None:
self._apple = None
elif self._apple is None:
raise ...
self._orange = value
答案 5 :(得分:0)
assert (apple is None) != (orange is None)
如果您将该代码放在__init__方法中,并且前提条件为false,则会抛出AssertionError
。