2 回答
TA贡献1936条经验 获得超6个赞
你需要一个@property
:
class Dummy:
def __init__(self, x):
self.x = x
@property
def x(self):
return self._x
@x.setter
def x(self, value):
if value is None:
raise Exception("x cannot be None")
self._x = value
d = Dummy(8)
d.x = 16
d.x = None # Raises
TA贡献1833条经验 获得超4个赞
注意:我将此处的问题解释为防止将所有属性设置为None之外的意思__init__,尽管在下面添加了一个选项来保护某些指定的属性。
这个怎么样?有__setattr__方法作为object.__setattr__.
class Dummy:
def __init__(self, x):
self._None_forbidden = False
self.z = None # this will work
self._None_forbidden = True
def __setattr__(self, k, v):
if v is None and self._None_forbidden:
raise ValueError("cannot set attribute to None")
object.__setattr__(self, k, v)
d = Dummy("foo")
print(d.z) # None
d.y = 2
print(d.y) # 2
d.x = None # raises ValueError
如果只是想保护某些属性,可以做成self._None_forbidden一组属性名,不允许设置为None。例如:
class Dummy:
def __init__(self, x):
self._None_forbidden = set()
self.z = None # this will work
self._None_forbidden.add("z")
def __setattr__(self, k, v):
if v is None and k in self._None_forbidden:
raise ValueError("cannot set attribute to None")
object.__setattr__(self, k, v)
d = Dummy("foo")
print(d.z) # None
d.y = 2
print(d.y) # 2
d.x = None
print(d.x) # None
d.z = 4
print(d.z) # 4
d.z = None # raises ValueError
显然,如果调用者操纵了_None_forbidden,那么这是可以规避的,但是他们应该知道他们正在做一些不受支持的事情。
添加回答
举报