在 Python 中自省构造函数 __init__ 的参数
Introspecting arguments from the constructor function __init__ in Python
有什么方法可以在不创建新实例的情况下从 __init__
中提取参数。
代码示例:
class Super:
def __init__(self, name):
self.name = name
我正在寻找类似 Super.__dict__.keys()
类型的解决方案。只是为了检索名称参数信息而不添加任何值。有这样的选择吗?
更新 Python 3.3+(正如 beeb 在评论中指出的那样)
您可以使用 Python 3.3 中引入的 inspect.signature
:
class Super:
def __init__(self, name, kwarg='default'):
print('instantiated')
self.name = name
>>> import inspect
>>> inspect.signature(Super.__init__)
<Signature (self, name, kwarg='default')>
原回答如下
您可以使用inspect
>>> import inspect
>>> inspect.getargspec(Super.__init__)
ArgSpec(args=['self', 'name'], varargs=None, keywords=None, defaults=None)
>>>
编辑:inspect.getargspec
实际上并没有创建 Super
的实例,见下文:
import inspect
class Super:
def __init__(self, name):
print 'instantiated'
self.name = name
print inspect.getargspec(Super.__init__)
这输出:
### Run test.a ###
ArgSpec(args=['self', 'name'], varargs=None, keywords=None, defaults=None)
>>>
请注意,instantiated
从未打印过。
在 class 字段中存储具体 __init__
参数的元class:
class ParameterReader(ABCMeta):
def __init__(cls, *args, **kwargs):
parameters = inspect.signature(cls.__init__).parameters
parameters = {key: value for key, value in parameters.items() if key not in ['self', 'args', 'kwargs']}
try:
cls._init_parameters = cls.__bases__[0]._init_parameters.copy()
cls._init_parameters.update(parameters)
except AttributeError:
cls._init_parameters = parameters
super().__init__(*args, **kwargs)
_init_parameters
然后可以在 class 实例内部或外部使用:
class Fruit(metaclass=ParameterReader):
def __init__(self, color):
print(color)
class Corn(Fruit):
def __init__(self, size, *args, **kwargs):
super().__init__(*args, **kwargs)
print(size)
print(self._init_parameters)
print(Corn._init_parameters)
制作中:
{'color': <Parameter "color">, 'size': <Parameter "size">}
以及在实例化中:
Corn(10, 'yellow')
制作中:
yellow
10
{'color': <Parameter "color">, 'size': <Parameter "size">}
请注意在 Corn 的 __init__ 参数中使用 *args
、**kwargs
是如何处理的。
有什么方法可以在不创建新实例的情况下从 __init__
中提取参数。
代码示例:
class Super:
def __init__(self, name):
self.name = name
我正在寻找类似 Super.__dict__.keys()
类型的解决方案。只是为了检索名称参数信息而不添加任何值。有这样的选择吗?
更新 Python 3.3+(正如 beeb 在评论中指出的那样)
您可以使用 Python 3.3 中引入的 inspect.signature
:
class Super:
def __init__(self, name, kwarg='default'):
print('instantiated')
self.name = name
>>> import inspect
>>> inspect.signature(Super.__init__)
<Signature (self, name, kwarg='default')>
原回答如下
您可以使用inspect
>>> import inspect
>>> inspect.getargspec(Super.__init__)
ArgSpec(args=['self', 'name'], varargs=None, keywords=None, defaults=None)
>>>
编辑:inspect.getargspec
实际上并没有创建 Super
的实例,见下文:
import inspect
class Super:
def __init__(self, name):
print 'instantiated'
self.name = name
print inspect.getargspec(Super.__init__)
这输出:
### Run test.a ###
ArgSpec(args=['self', 'name'], varargs=None, keywords=None, defaults=None)
>>>
请注意,instantiated
从未打印过。
在 class 字段中存储具体 __init__
参数的元class:
class ParameterReader(ABCMeta):
def __init__(cls, *args, **kwargs):
parameters = inspect.signature(cls.__init__).parameters
parameters = {key: value for key, value in parameters.items() if key not in ['self', 'args', 'kwargs']}
try:
cls._init_parameters = cls.__bases__[0]._init_parameters.copy()
cls._init_parameters.update(parameters)
except AttributeError:
cls._init_parameters = parameters
super().__init__(*args, **kwargs)
_init_parameters
然后可以在 class 实例内部或外部使用:
class Fruit(metaclass=ParameterReader):
def __init__(self, color):
print(color)
class Corn(Fruit):
def __init__(self, size, *args, **kwargs):
super().__init__(*args, **kwargs)
print(size)
print(self._init_parameters)
print(Corn._init_parameters)
制作中:
{'color': <Parameter "color">, 'size': <Parameter "size">}
以及在实例化中:
Corn(10, 'yellow')
制作中:
yellow
10
{'color': <Parameter "color">, 'size': <Parameter "size">}
请注意在 Corn 的 __init__ 参数中使用 *args
、**kwargs
是如何处理的。