(Python 3.7)
pint / Q_ behavior
I want to subclass pint's quantity class and override __init__
. The standard syntax fails because apparently the arguments bubble up to the object
init method (which takes no argument):
# file: test.py
from pint import UnitRegistry
ureg = UnitRegistry()
Q_ = ureg.Quantity
class Q_Child_(Q_):
def __init__(self, *args, **kwargs):
super(Q_, self).__init__(*args, **kwargs)
self.foo = 'foo'
a=Q_Child_(1.0, 's') # Raises an error:
# Traceback(most recent call last):
# File ".../test.py", line 12, in < module >
# a = Q_Child_(1.0, 's')
# File ".../test.py", line 9, in __init__
# super(Q_, self).__init__(*args, **kwargs)
# TypeError: object.__init__() takes exactly one argument(the instance to initialize)
What seems to work is to not call super/init at all in the subclassing, but how does this even make sense?
from pint import UnitRegistry
ureg = UnitRegistry()
Q_ = ureg.Quantity
class Q_Child_(Q_):
def __init__(self, *args, **kwargs):
# not calling super or Q_.__init__ (or so it seems)
self.foo = 'foo'
a=Q_Child_(1.0, 's')
print(a) # '1.0 second' -> how does it even know the passed arguments?
print(a.foo) # 'foo'
I believe the latter is what I want to use, but using code that works when you think it should not work seems a recipe for disaster. What is happening?
I guess it is due to Q_
being generated dynamically (when ureg
is instantiated, see https://github.com/hgrecco/pint/blob/master/pint/registry.py#L115 and https://github.com/hgrecco/pint/blob/master/pint/quantity.py#L1741) but fail to see why it should matter.
That question is not a duplicate of correct way to use super (argument passing) (or similar) because the standard way does not work here:
class NewDict(dict):
def __init__(self, *args, foo='foo', **kwargs):
super(NewDict, self).__init__(*args, **kwargs)
self.foo = foo
nd = NewDict({'a': 1}, foo='bar')
print(nd) # {'a': 1}
print(nd.foo) # 'bar'
Without the super
call, the parent class has no way to know the arguments that it is supposed to initialize with:
class NewDictWithoutSuper(dict):
def __init__(self, *args, foo='foo', **kwargs):
self.foo = foo
nd = NewDictWithoutSuper({'a': 1}, foo='bar')
print(nd) # {} i.e. the default dict()
print(nd.foo) # 'bar'