ARTICLE AD BOX
While you can handle initialization in the __new__ method, because it's always called before __init__ (or even instead of, if __new__'s returned object is other than an instance of the class), it's best practice decoupling object initizalization in __init__ and leaving __new__ only for object creation.
For instance, in that way you would be able to subclass Foo. (Furthermore, passing *args, **kwargs to __new__ will allow the subclass have any number of positional or named arguments.)
class Foo(float): def __new__(cls, value, *args, **kwargs): return super().__new__(cls, value) def __init__(self, value, extra): self.extra = extra class SubFoo(Foo): def __init__(self, value, extra, more): super().__init__(value, extra) self.more = moreHowever, if you handle initialization in __new__ you will inherit object's __init__ which hasn't more arguments than the instance itself. And you won't be able to subclass it by the common way.
class Bar(float): def __new__(cls, value, extra): self = super().__new__(cls, value) self.extra = extra return self class SubBar(Bar): def __init__(self, value, extra): super().__init__(value, extra) >>> sub_bar = SubBar(1, 2) TypeError: object.__init__() takes no parameters