Issue 1416. Add getter, setter, deleter methods to properties that can be

used as decorators to create fully-populated properties.
This commit is contained in:
Guido van Rossum 2007-11-10 22:12:24 +00:00
parent d3ffd341b8
commit d1ef78942a
2 changed files with 120 additions and 1 deletions

View File

@ -2131,6 +2131,71 @@ def properties():
p = property(_testcapi.test_with_docstring)
def properties_plus():
class C:
foo = property(doc="hello")
@foo.getter
def foo(self):
return self._foo
@foo.setter
def foo(self, value):
self._foo = abs(value)
@foo.deleter
def foo(self):
del self._foo
c = C()
assert C.foo.__doc__ == "hello"
assert not hasattr(c, "foo")
c.foo = -42
assert c.foo == 42
del c.foo
assert not hasattr(c, "foo")
class D(C):
@C.foo.deleter
def foo(self):
try:
del self._foo
except AttributeError:
pass
d = D()
d.foo = 24
assert d.foo == 24
del d.foo
del d.foo
class E:
@property
def foo(self):
return self._foo
@foo.setter
def foo (self, value):
raise RuntimeError
@foo.setter
@foo.deleter
def foo(self, value=None):
if value is None:
del self._foo
else:
self._foo = abs(value)
e = E()
e.foo = -42
assert e.foo == 42
del e.foo
class F(E):
@E.foo.deleter
def foo(self):
del self._foo
@foo.setter
def foo(self, value):
self._foo = max(0, value)
f = F()
f.foo = -10
assert f.foo == 0
del f.foo
def supers():
if verbose: print "Testing super..."

View File

@ -1108,6 +1108,60 @@ static PyMemberDef property_members[] = {
{0}
};
PyDoc_STRVAR(getter_doc,
"Descriptor to change the getter on a property.");
PyObject *
property_getter(PyObject *self, PyObject *getter)
{
Py_XDECREF(((propertyobject *)self)->prop_get);
if (getter == Py_None)
getter = NULL;
Py_XINCREF(getter);
((propertyobject *)self)->prop_get = getter;
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(setter_doc,
"Descriptor to change the setter on a property.\n");
PyObject *
property_setter(PyObject *self, PyObject *setter)
{
Py_XDECREF(((propertyobject *)self)->prop_set);
if (setter == Py_None)
setter = NULL;
Py_XINCREF(setter);
((propertyobject *)self)->prop_set = setter;
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(deleter_doc,
"Descriptor to change the deleter on a property.");
PyObject *
property_deleter(PyObject *self, PyObject *deleter)
{
Py_XDECREF(((propertyobject *)self)->prop_del);
if (deleter == Py_None)
deleter = NULL;
Py_XINCREF(deleter);
((propertyobject *)self)->prop_del = deleter;
Py_INCREF(self);
return self;
}
static PyMethodDef property_methods[] = {
{"getter", property_getter, METH_O, getter_doc},
{"setter", property_setter, METH_O, setter_doc},
{"deleter", property_deleter, METH_O, deleter_doc},
{0}
};
static void
property_dealloc(PyObject *self)
@ -1260,7 +1314,7 @@ PyTypeObject PyProperty_Type = {
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
property_methods, /* tp_methods */
property_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */