3

I'm finding that inheriting from a base class can change the derived class signature according to inspect.signature, and I would like to understand how that happens. Specifically, the base class in question is tensorflow.keras.layers.Layer:

import sys
import inspect
import tensorflow as tf

class Class1(tf.keras.layers.Layer):
    def __init__(self, my_arg: int):
        pass

class Class2:
    def __init__(self, my_arg: int):
        pass

print("Python version: ", sys.version)
print("Tensorflow version: ", tf.__version__)
print("Class1 signature: ", inspect.signature(Class1))
print("Class2 signature: ", inspect.signature(Class2))

Outputs

Python version:  3.8.10 (default, Mar 23 2023, 13:10:07)
[GCC 9.3.0]
Tensorflow version:  2.12.0
Class1 signature:  (*args, **kwargs)
Class2 signature:  (my_arg: int)

I tried running the code above and I expected it to print the same signature for both classes.

Andrea Allais
  • 447
  • 4
  • 6
  • 1
    Does this answer your question? [What are metaclasses in Python?](https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python) – mousetail Aug 17 '23 at 19:07

1 Answers1

1

This is a bug behavior that is unique to earlier versions of Python, including 3.8 and early patch releases of Python 3.9/3.10

In 3.8 and 3.9.4:

Class1 signature:  (*args, **kwargs)
Class2 signature:  (my_arg: int)

In newer versions of Python, like 3.9.17 and latest versions of 3.10 and 3.11, the result is how you would expect:

Class1 signature:  (my_arg: int)
Class2 signature:  (my_arg: int)

I'm not 100% sure what exactly changed the behavior between these python versions, but my best guess is that this is related to either this issue or this issue, which were fixed in Python3.11 and backported to some earlier Python versions. However, Python3.8 did not receive any of these backport fixes.

sytech
  • 29,298
  • 3
  • 45
  • 86
  • Yes this is right. I verified that `keras.Layer` does in fact define a `__new__` method, and also that inheriting from a simpler class that only defines a `__new__` method reproduces the issue. Thanks for the quick response. – Andrea Allais Aug 17 '23 at 20:11
  • Ah, yes @AndreaAllais -- this issue may have some relevant discussion of the problem (or maybe a related problem): [CPython GH-105080](https://github.com/python/cpython/issues/105080) – sytech Aug 17 '23 at 20:17