I just wanted to use the descriptor pattern, but it didn't seem to work that well. Here is a short example (without any real use, just to show):
class Num(object):
  def__init__(self, val=0):
    self.val = val
  def __get__(self, instance, owner):
    return self.val
  def __set__(self, instance, val):
    self.val = val
  def __str__(self):
    return "Num(%s)" % self.val
  def __repr__(self):
    return self.__str__()
class Test(object):
  def __init__(self, num=Num()):
    self.num = num
and the Test:
>>>t = Test()
>>>t.num # OK
Num(0)
>>>t.num + 3 #OK i know how to fix that, but I thought __get__.(t.num, t, Test) will be called
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Num' and 'int'
>>> t.num = 4 # why isn't __set__(t.num, t, 4) called here?
>>> t.num
4
What is my misconception here?
                        
Descriptors only work when they are attributes of a class, not an instance. If you change your class to:
. . . then the descriptor will work.
However, because the descriptor has to be set on the class, that means there is only one instance of the descriptor, so it's probably not a good idea for the descriptor to store its values on
self. Such values will be shared across all instances of the class. Instead, set the value oninstance.Also, note that your
__str__and__repr__will probably not do what you think they will. Callingt.numwill activate the descriptor and return itsval, so the result oft.numwill be the plain number 0, not aNuminstance. The whole point of the descriptor is to transparently return the result of__get__without making the descriptor object itself visible.Here are some illustrative examples:
With an alternate version of the descriptor: