这是一种避免假设的方法
所有用户都是同意的成年人,因此有责任自己正确使用事物。
请在下面查看我的更新
使用@property
, 非常冗长,例如:
class AClassWithManyAttributes:
'''refactored to properties'''
def __init__(a, b, c, d, e ...)
self._a = a
self._b = b
self._c = c
self.d = d
self.e = e
@property
def a(self):
return self._a
@property
def b(self):
return self._b
@property
def c(self):
return self._c
# you get this ... it's long
使用
没有下划线:它是一个公共变量。
一个下划线:它是一个受保护的变量。
两个下划线:它是一个私有变量。
除了最后一个,这是一个约定。如果您真的很努力,您仍然可以使用双下划线访问变量。
那么我们该怎么办?我们是否放弃在 Python 中拥有只读属性?
看哪!read_only_properties
装修师傅来救场!
@read_only_properties('readonly', 'forbidden')
class MyClass(object):
def __init__(self, a, b, c):
self.readonly = a
self.forbidden = b
self.ok = c
m = MyClass(1, 2, 3)
m.ok = 4
# we can re-assign a value to m.ok
# read only access to m.readonly is OK
print(m.ok, m.readonly)
print("This worked...")
# this will explode, and raise AttributeError
m.forbidden = 4
你问:
read_only_properties
来自哪里?
很高兴你问,这里是read_only_properties的来源:
def read_only_properties(*attrs):
def class_rebuilder(cls):
"The class decorator"
class NewClass(cls):
"This is the overwritten class"
def __setattr__(self, name, value):
if name not in attrs:
pass
elif name not in self.__dict__:
pass
else:
raise AttributeError("Can't modify {}".format(name))
super().__setattr__(name, value)
return NewClass
return class_rebuilder
更新
没想到这个答案会引起这么多关注。令人惊讶的是它确实如此。这鼓励我创建一个你可以使用的包。
$ pip install read-only-properties
在你的 python 外壳中:
In [1]: from rop import read_only_properties
In [2]: @read_only_properties('a')
...: class Foo:
...: def __init__(self, a, b):
...: self.a = a
...: self.b = b
...:
In [3]: f=Foo('explodes', 'ok-to-overwrite')
In [4]: f.b = 5
In [5]: f.a = 'boom'
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-a5226072b3b4> in <module>()
----> 1 f.a = 'boom'
/home/oznt/.virtualenvs/tracker/lib/python3.5/site-packages/rop.py in __setattr__(self, name, value)
116 pass
117 else:
--> 118 raise AttributeError("Can't touch {}".format(name))
119
120 super().__setattr__(name, value)
AttributeError: Can't touch a