Python 如何获取参数';函数的类型和返回类型?

Python 如何获取参数';函数的类型和返回类型?,python,types,genetic-programming,Python,Types,Genetic Programming,我正在尝试用python实现强类型的遗传编程 有类似的样品吗 def funcA(a,b): return a + b return_type(funcA) output: <class 'Integer'> 没有机会。由于python使用duck类型,所以可以将不同类型的参数(例如int和int、str和str等)传递给funcA。如果看不到实际参数,就无法判断返回类型和参数类型。最好的方法是使用docstring来存储函数和参数的此类信息 In [49]: def fun

我正在尝试用python实现强类型的遗传编程

有类似的样品吗

def funcA(a,b):
  return a + b
return_type(funcA)

output: <class 'Integer'>

没有机会。由于python使用duck类型,所以可以将不同类型的参数(例如int和int、str和str等)传递给funcA。如果看不到实际参数,就无法判断返回类型和参数类型。最好的方法是使用docstring来存储函数和参数的此类信息

In [49]: def funcA(a,b):
   ....:     ''' returns an int '''
   ....:     return int(a+b)
   ....:

In [50]: funcA.__doc__
Out[50]: ' returns an int '

Python3引入了函数注释。他们自己什么也不做,但你可以自己写:

def strict(fun):
    # inspect annotations and check types on call

@strict
def funcA(a: int, b: int) -> int:
    return a + b 

这是不可能的-你自己的例子证明了这一点,想象一下你这样称呼它:

funcA(1, 2)
你得到了
3
,一个整数,但是这个呢:

funcA("Test", "Test")
您将得到
“TestTest”
,一个字符串!Python不关心类型,也不保证函数输出单个类型。这也会对
float
s或
list
s产生不同的结果。除此之外,还可以显式返回不同类型的对象


总的来说,这是一件好事。这意味着您不需要担心类型是否正确,只需要担心是否可以处理您传递的内容。这使得Python非常灵活。

在Python中,只有执行调用并执行
return
语句,才能知道返回类型。它甚至可以在不同的情况下有所不同,因此简短的回答是“不可能的”

如果您需要知道某个函数的返回类型,您仍然可以将其包装到一些类型检查代码中,这些代码也可以公开返回类型。然而,这将是相当不和谐的:

def declare_return_type(t):
    def decorator(f):
        def wrapper(*a, **kw):
            res = f(*a, **kw)
            assert isinstance(res, t)
            return res
        wrapper.return_type = t
        return wrapper
    return decorator

@declare_return_type(int)
def f(a, b):
    return a + b

print f.return_type

print f(1, 2) # ok
f('a', 'b') # Assertion error

UPD:您可以对参数类型执行相同的操作,并检查它们。

在动态类型语言Python中,函数参数的类型信息在运行时是必需的。在3.3及更高版本中,您可以获得如下函数类型:

from inspect import signature
def foo(a, *, b:int, **kwargs):
...     pass

sig = signature(foo)

str(sig)
'(a, *, b:int, **kwargs)'

str(sig.parameters['b'])
'b:int'

sig.parameters['b'].annotation
<class 'int'>
来自检查导入签名
def foo(a,*,b:int,**kwargs):
...     通过
sig=签名(foo)
str(sig)
“(a,*,b:int,**kwargs)”
str(信号参数['b'])
“b:int”
符号参数['b'].注释

请参见

您可以通过注释检查:

def func(a:str)->int: #代码 >>>函数注释[“返回”] 参数也一样:

函数注释
请用您正试图解决的确切问题更新您的问题,您认为这就是解决方案,因为在Python这样的松散类型语言中,这种范例没有意义。如果你传递你自己的对象,你可以这样做,但我再次怀疑这样的要求是否明智。docstring为+1,但公平地说,你应该有
返回int(a+b)
。值得注意的是,在Python中强制某些类型的东西是一个坏主意,因为它会降低你的函数的有用性。再次,值得注意的是,类型检查通常不是一个好主意。它会使你的函数变得不那么有用,而且通常对你没有帮助。在某些非常特定的情况下,它可能很有用,但不应该理所当然地这样做-如果您想这样做,请编写Java。但这是解决我的问题的一个好主意:D很高兴看到python可以是强类型、严格类型和动态的。不幸的是,没有在编译类型上执行检查,由于语言的性质,我们对此无能为力。我不会说它看起来像一个经典的“强类型”。当然,您可以执行任何类型的检查。但仅在执行时。@JosieThompson Duck typing意味着依赖对象的功能(它是否有
quack()
方法?)来确定它的身份(如果有,它就是Duck)。类型检查是指检查对象的实际类型(是否为
Duck
对象?)。@GarethLatty您的后一个注释是主观的,并且是基于意见的。如果你重新阅读我最初的评论,你会看到“我根据项目的上下文[…]选择一种程序语言”,而不是基于非功能特性,如强类型。事实上,我不喜欢python有一千个原因,但在我的MSc论文中,我用python编写了整个项目系统(提示,提示)。也许是我冒犯了你,把你的语言称为可憎的语言;但这不是我的意图,因为这只是我个人的意见。我从来没有提到过Java?!?很酷的比喻
def declare_return_type(t):
    def decorator(f):
        def wrapper(*a, **kw):
            res = f(*a, **kw)
            assert isinstance(res, t)
            return res
        wrapper.return_type = t
        return wrapper
    return decorator

@declare_return_type(int)
def f(a, b):
    return a + b

print f.return_type

print f(1, 2) # ok
f('a', 'b') # Assertion error
from inspect import signature
def foo(a, *, b:int, **kwargs):
...     pass

sig = signature(foo)

str(sig)
'(a, *, b:int, **kwargs)'

str(sig.parameters['b'])
'b:int'

sig.parameters['b'].annotation
<class 'int'>