如何避免在不通过引用传递的情况下重复Python中的工作?

时间:2017-02-16 02:39:12

标签: python parameter-passing jwt dry code-duplication

我正在编写采用JSON Web令牌(JWT)的Web端点,并且必须检查令牌上的签名。因为每次对我来说最有意义的时候我都会检查签名,因为DRY,我应该把这个步骤分解成一个函数。

但是,检查JWT是否正确签名的唯一方法是使用其密钥对其进行解码并捕获错误。这引出了以下功能:

def is_valid_token(token_string, secret_key):
    try:
        jwt.decode(token_string, secret_key)
        return True
    except jwt.DecodeError:
        return False

这在验证令牌方面工作正常,但是我有这个函数来检查令牌是否有效通过解码然后在此函数之后我将不得不再次解码似乎真的很浪费。也就是说我会这样做:

if not is_valid_token(token_string, secret_key):
    # Respond with an error to the client
else:
    token_data = jwt.decode(token_string, secret_key)

在这种情况下,我正在解码以检查它是否有效,然后我是否再次解码。在C / C ++中,我将通过引用传递一个变量来捕获解码数据,然后返回true或false。有没有办法在Python中做这样的事情?

我突然意识到,我可以通过传入一个空列表来捕获解码数据,但这似乎真的很不优雅。是否有Pythonic方法来做到这一点?

3 个答案:

答案 0 :(得分:1)

在与Nullman讨论后,我们得出以下解决方案

def is_valid_token(jwt_string, secret_key, reference_list):
    try:
        data = jwt.decode(jwt_string, secret_key)
        reference_list.append(data) 
        return True
    except:
        return False

reference_var = []
if not is_valid_token(jwt_string, secret_key, reference_var):
    # Respond with an error to the client
else:
    data = reference_var[0]

答案 1 :(得分:1)

你的方法已经使用了一个好的Pythonic EAFP成语,但它会把它变成C样式LBYL返回码检查模式。不要这样做,继续使用例外。

在这种情况下,is_valid_token有点毫无意义;当您仍需要基于其返回值的if / else时,它实际上不会保存任何内容。根本不进行测试,只需进行内联解析并处理异常(如果发生):

try:
    token_data = jwt.decode(token_string, secret_key)
except jwt.DecodeError:
    # respond with error to client
else:
    # Use token_data

它没有更多的冗长(你可以通过将else块的内容放在try中,如果没有其他任何东西可以引发jwt.DecodeError,那么它就可以缩短它。详细信息为if / else)。

如果这是更深层嵌套的代码,你甚至可能不会在这里捕获异常,但让它冒泡堆栈,直到知道如何响应客户端的人收到它。

同样,重申一下,你的问题是尝试使用LBYL习语,看看你是否被允许做某事,然后去做,当最简单的方法是做它并处理异常(如果它发生)。你实际上没有避免DRY,因为在解析时不是RY,你在检查返回并使用结果时最终会RY。

答案 2 :(得分:1)

编辑:正如@ShadowRanger指出的那样,下面的代码应该可行,但它实际上并没有改进任何东西,需要从__init__再加注异常,并且调用者需要检查它。所以这个包装并没有真正帮助。我会留下答案供参考,但正确的方法可能是@ShadowRanger's answer

也许你可以在这里利用类继承:

class WebEndPoint(object):
    def __init__(self, token_string, secret_key)
        try:
            self.data = jwt.decode(token_string, secret_key)
        except jwt.DecodeError as e:
            # respond with "invalid token"
            raise e

然后在您的代码中,您可以使用类:

class MyEndpoint(WebEndPoint):
    def handle_request(self,...):
        # do something with self.data, which you know is
        # valid if you reach this point

myendpoint = MyEndPoint(token, secret)

这样您根本不需要拨打is_valid(),但实际执行此操作的方式可能取决于您使用的框架(如果有)。