And by best, I mean both Pythonically and with as few lines of code as possible.
I am used to defining classes with attributes in Python like so.
class MyClass(object):
def __init__(self):
self.value = 5
Often, however, I find myself needing to ensure that self.value
can only take a specific type of value. In the past (coming from a PHP OOP background) I've done this with a getter-setter method similar to this:
def value(self, new_value = -1)
if new_value == -1:
return self.value
if isinstance(new_value, int) and new_value > -1:
self.value = new_value
else:
raise TypeError
I then access self.value
with self.value()
, and set it with self.value(67)
. Usually I'll name-mangle self.value
to self.__value
to discourage its direct access.
I've recently discovered (or am in the process of discovering) descriptors. Following closely the excellent discussion here I've written something that looks like this:
class ValidatedAttribute(object):
def __init__(self, key, kind):
self.key = key
self.kind = kind
def __get__(self, instance, owner):
if self.key not in instance.__dict__:
raise AttributeError, self.key
return instance.__dict__[self.key]
def __set__(self, instance, value):
if not isinstance(value, self.kind):
raise TypeError, self.kind
instance.__dict__[self.key] = value
class MyUsefulClass(object):
a = ValidatedAttribute("a", int)
But I have a few questions!
Firstly, what exactly is MyUsefulClass().a
? Is it an instance of a ValidatedAttribute class somehow bound to an instance of a MyUsefulClass
class?
And secondly, what I'd really like is something like,
class MyUsefulClass(object):
def __init__(self):
self.value = Checker(int, 99)
def Checker(self, kind, default):
# Code for verifying that associated attribute is of type kind.
and somehow bind an attribute access to some sort of intercept method, without having to use a whole other descriptor class.
I'm sorry if my understanding is lacking - I'm still getting to grips with new-style Python classes. Any help or pointers in the right direction would be much appreciated.