这里有一种方法可以避免假设所有用户都是成年人,并因此对自己正确使用事物负责的假设。
请注意下面我的更新
使用@property非常冗长,例如:
请看下面的更新
使用@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
使用
无下划线:它是公共变量。
一个下划线:它是受保护的变量。
两个下划线:它是私有变量。
除了最后一个,这是一种惯例。如果你真的很努力,你仍然可以访问双下划线变量。
那么我们该怎么办?在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
print(m.ok, m.readonly)
print("This worked...")
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 shell中:
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
self.x
并相信没有人会更改x
。如果确保x
不能被更改很重要,那么请使用属性。 - li.davidm_x
根本不是奇数:按照惯例,它表示某些“私有”的东西。 - li.davidmobj.x
,您的类必须是新式类,也就是继承自object
。在旧式类中,您实际上仍然可以设置obj.x
,但会得到一些意外的结果。 - Ian H