从第二个函数调用返回相同的值

时间:2020-07-04 03:24:51

标签: python

如果第一个函数调用了第二个函数,那么第二个函数是否可以为第一个函数返回值

def check_type(x):
  if type(x) not in [int, float]:
    return None

def square(x):
  check_type(x)
  return x**2


print(square(2))
>>> 4

print(square('2'))
>>> Error but should return None

我知道我可以通过使用if then语句来重组代码,使之成为可能,但是我想看看Python是否已内置任何东西来保存代码行。

4 个答案:

答案 0 :(得分:5)

从概念上讲,您可能希望切换功能的顺序。您可以让square接受check_type作为回调,如果一切都通过,则使用经过清理的参数进行调用,而不是check_type使用square来检查其参数。

天真的方法可能如下:

def check_type(x, hook):
    return hook(x) if type(x) in [int, float] else None

def square(x):
    return x**2


print(check_type(2, square))
# 4

print(check_type('2', square))
# None

这不是超级优雅,但是它在许多方面都对您的原始方法进行了设计改进。一方面,函数square可以自由地专注于完成其工作,而不必担心清理参数(这有助于封装)。另一方面,它使类型检查在各个函数之间更加一致,因为您可以在一个地方完成它,而不必记住在每个函数中都要做。

就优雅程度而言,python提供了一种非常干净的方法来执行此操作,称为装饰器。装饰器是一个接受函数或类作为输入并返回替换对象的函数。通常,这通常用于包装带有其他功能的功能,就像您尝试做的一样。

第一遍装饰器实现如下所示:

from functools import wraps

def check_type(func):
    @wraps(f)
    def wrapper(x):
        return func(x) if type(x) in [int, float] else None
    return wrapper

@check_type
def square(x):
    return x**2


print(square(2))
# 4

print(square('2'))
# None

请注意,装饰器返回的用于替换wrapper的{​​{1}}函数本身就是装饰的。 functools.wraps通过更新名称和其他属性来修改功能对象,以使square与原始wrapper更加难以区分。

在不相关的注释上,我可能不允许我的函数在不适当的输入上返回值。当您返回square时,您将迫使调用者检查None与有效值之间的距离,从而实际上违反了首先使用类型检查器的目的。相反,例外是更好的设计选择,因为它不会降低责任:

None

最后,您可能需要重新考虑如何进行类型检查或是否完全进行类型检查。例如,您可以扩展大多数内置类。如果您想允许此类扩展名,可以使用更好的措辞

def check_type(func):
    @wraps(f)
    def wrapper(x):
        if type(x) in [int, float]
            raise TypeError ('Expected one thing but got the other')
        return func(x)
    return wrapper

或者您可以使用在numbers模块中注册的抽象基类。这将使您能够处理诸如numpy标量,十进制等的内容:

if isinstance(x, (int, float)):

最后,您可能要考虑做最Python的事情,并传递支持所需操作的所有内容。这意味着根本不进行任何类型检查。如果您传递的内容实例没有if isinstance(x, numbers.Number): 方法,则解释器将在__pow__中为您引发TypeError

答案 1 :(得分:4)

如果您想保存代码行(并不是说这始终是一个道德目标),则可以对以下内容使用布尔短路:

def check_type(x):
    return type(x) in [int, float] or None

def square(x):
    return check_type(x) and x**2


print(square(2))
# 4

print(square('2'))
# None

如果它为假,它将返回check_type(x)的值,否则返回值square()

话虽如此,看来pythonic的方法是不进行类型检查,而是捕获错误:

def square(x):
    try:
        return x**2
    except TypeError:
        return None

这将使您的函数可以处理您可能无法预测的其他类型,但允许使用指数。例如,复数:square(2+1j)在第一个示例中返回None,在第二个示例中返回(3+4j)

答案 2 :(得分:1)

def check_type(x):
  if type(x) not in [int, float]:
    return None

这里的问题是,当您的类型不是intfloat时,您将返回None,但是当您的值处于所需类型时,它什么也不返回。

因此,实际上类型检查没有返回任何内容,并且您不能在不编写return语句的情况下从函数中返回,即,当您调用check_type时,它返回None(来自check_type),但是从{{1 }}功能。

马克·迈耶的答案很完美

它也应该工作-

sqauare

答案 3 :(得分:1)

check_type(x)始终向Square(x)返回None,但不让square(x)返回None。

尝试一下

def square(x):
    return x**2 if isinstance(x , (int, float)) else None
相关问题