This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Subclassing int and complex with keyword arguments weird
Type: Stage: resolved
Components: Library (Lib) Versions: Python 3.9
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Dennis Sweeney, autospamfighter, mark.dickinson, terry.reedy
Priority: normal Keywords:

Created on 2020-11-12 18:23 by autospamfighter, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (5)
msg380840 - (view) Author: autospamfighter (autospamfighter) Date: 2020-11-12 18:23
I was trying to make a custom complex class that looked something like this and it failed. I replaced complex with int and it also failed, but I tried float and it worked.

---fail
class A(complex):
    def __init__(self, test):
        super().__init__()

A(test=5)

---fail
class A(int):
    def __init__(self, test):
        super().__init__()

A(test=5)

---work
class A(float):
    def __init__(self, test):
        super().__init__()

A(test=5)
msg380842 - (view) Author: autospamfighter (autospamfighter) Date: 2020-11-12 18:50
I tried some more classes and str is weird, but dict and set work fine. very weird
msg380870 - (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python committer) Date: 2020-11-13 05:36
This is because int, str, and complex are immutable. If I have 

    class MyInt(int):
        def __init__(self, stuff):
            pass

then when I call MyInt("19"), the string "19" is passed to the constructor int.__new__ before the overridden initializer MyInt.__init__. You can only override that by implementing a MyInt.__new__ to override the int constructor.

This is not a bug.
msg380871 - (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python committer) Date: 2020-11-13 05:41
Here's an example:

class A(complex):
    def __init__(self, *args, test):
        self.test = test
    def __new__(cls, *args, test):
        return super().__new__(cls, *args)

>>> a = A(1, test="TEST")
>>> a
(1+0j)
>>> a.test
'TEST'

>>> b = A(1, 1, test="TEST2")
>>> b
(1+1j)
>>> b.test
'TEST2'
msg380964 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2020-11-14 08:57
When reporting a failure please copy and paste the exception and message and when non-trivial, the traceback.   In this case:  "TypeError: 'test' is an invalid keyword argument for complex()".  The difference between int and complex versus float is that the former have keyword arguments, so they check for invalid keyword arguments, whereas float take no keyword arguments, so it does not check for validity and, for subclasses, passes them on.
History
Date User Action Args
2022-04-11 14:59:38adminsetgithub: 86500
2020-11-14 08:57:55terry.reedysetstatus: open -> closed

nosy: + terry.reedy
messages: + msg380964

resolution: not a bug
stage: resolved
2020-11-13 11:43:05mark.dickinsonsetnosy: + mark.dickinson
2020-11-13 05:41:37Dennis Sweeneysetmessages: + msg380871
2020-11-13 05:36:10Dennis Sweeneysetnosy: + Dennis Sweeney
messages: + msg380870
2020-11-12 18:50:33autospamfightersetmessages: + msg380842
2020-11-12 18:23:57autospamfightercreate