mirror of
https://github.com/python/cpython.git
synced 2025-08-01 07:33:08 +00:00
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:
parent
d3ffd341b8
commit
d1ef78942a
2 changed files with 120 additions and 1 deletions
|
@ -2131,6 +2131,71 @@ def properties():
|
||||||
p = property(_testcapi.test_with_docstring)
|
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():
|
def supers():
|
||||||
if verbose: print "Testing super..."
|
if verbose: print "Testing super..."
|
||||||
|
|
||||||
|
|
|
@ -1108,6 +1108,60 @@ static PyMemberDef property_members[] = {
|
||||||
{0}
|
{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
|
static void
|
||||||
property_dealloc(PyObject *self)
|
property_dealloc(PyObject *self)
|
||||||
|
@ -1260,7 +1314,7 @@ PyTypeObject PyProperty_Type = {
|
||||||
0, /* tp_weaklistoffset */
|
0, /* tp_weaklistoffset */
|
||||||
0, /* tp_iter */
|
0, /* tp_iter */
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
0, /* tp_methods */
|
property_methods, /* tp_methods */
|
||||||
property_members, /* tp_members */
|
property_members, /* tp_members */
|
||||||
0, /* tp_getset */
|
0, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue