2

This is what I'm doing:

class D(float):
    def __init__(self, name):
        self._name = name
        print name

But when I try to initialize on object of type D:

d = D('aaa')

I get this error:

Traceback (most recent call last):
  File "/home/user/untitled1.py", line 22, in <module>
    d = D('aaa')
ValueError: could not convert string to float: aaa

Why? I'm not initializing a float, just setting a name. I didn't call the __init__ of float.

alko
  • 46,136
  • 12
  • 94
  • 102
Alvaro Fuentes
  • 16,937
  • 4
  • 56
  • 68
  • I've read the other [question](http://stackoverflow.com/questions/1936457/sub-classing-float-type-in-python-fails-to-catch-exception-in-init) and I don't think it's a duplicate. That question just want to overwrite `__str__` and I'm trying just to set a name attribute in my class. I'm trying with the `__new__` constructor but I could'n manage how to solve the problem, so I think the question is still valid! – Alvaro Fuentes Dec 19 '13 at 21:21

1 Answers1

2

The reason is that prior to inititalizer, that is __init__ function, a constructor, that is __new__, is called. It is called with the same arguments as __init__. As for your class it is not defined, it's superclass' one, that is float's, is called, and error is raised. You can see it if you wrap constructor:

>>> class D(float):
...     def __new__(cls, *args, **kwargs):
...         print cls, args, kwargs
...         return super(D, cls).__new__(cls, *args, **kwargs)
...     def __init__(self, value):
...         print value
...
>>> D('a')
<class '__main__.D'> ('a',) {}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __new__
ValueError: could not convert string to float: a

If you want add custom attributes, use something like follows:

>>> class D(float):
...     __slots__ = ['name']
...     def __new__(cls, *args, **kwargs):
...         name = kwargs.pop('name')
...         obj = super(D, cls).__new__(cls, *args, **kwargs)
...         obj.name = name
...         return obj
...
>>> d = D(0, name='d')
>>> e = D(1, name='e')
>>> d, d.name
(0.0, 'd')
>>> e, e.name
(1.0, 'e')
alko
  • 46,136
  • 12
  • 94
  • 102