python的类型暗示:记一次神奇的debug经历

今天用python写密码学作业,本地运行无误的代码放到OJ平台上,全部runtime error, 而且运行时间0,消耗空间0.

本地能过,OJ上不能过,最容易想到的就是操作系统的差异。但是python是跨平台的,运行结果理应操作系统无关。

后来想到是不是import了非标准模块或者非本py文件的函数(我们的OJ只能上传单个代码文件),扫了一眼发现没有。为了确认,把文件从project文件夹里拖出来,再运行还是能跑。又把py文件和输入数据发给室友,让他帮我运行一下。发现也能跑出来正确结果,和我本地运行的结果一样。

此时突然灵光一现:因为python是弱类型的,我写函数时,为了方便日后调用时少弹Type Error以及各种因为类型不对导致的可能更隐蔽的bug,我会用类型暗示标注一下参数类型,类似于

def func(parameter: type){
    do_something();
}

这不是一个陈旧的语法,查了一下3.5开始才出现。那么应该是OJ的python版本比较低吧,而我本地的python版本是3.9。于是利用OJ的自测功能,获取OJ上python的版本。

import sys


print(sys.version)

输出:

3.6.8 (default, Aug 20 2019, 17:12:48) 
[GCC 8.3.0]

人家OJ的python版本支持类型暗示。。。灵光一现也没找到结果,真的给我整不会了。后来把代码分块放到OJ上跑(此时有点怀疑是获取输入的那一段代码有问题

获取输入的代码如下:

    bytes = []
    k = int(input(), 16)
    op = bool(int(input()))
    for line in sys.stdin:
        bytes += list(map(lambda x: int(x, 16), line.split()))

一开始是获取输入的代码连同一堆函数定义一起传给OJ的,依然Runtime Error.

后来把所有函数定义都删了,只剩下获取输入的代码,竟然没报错了!

看来导致runtime Error的bug不在代码执行的部分(也就是__name__ == '__main__'下),而在函数定义的部分。(这也解释了为什么运行时间0,消耗空间0,因为它还没真正跑就报Error了)

后来把自己写的各个函数定义一个一个上传,其中

def zero_fill(byte_: int):
    s = hex(byte_)
    return '0x' + (4 - len(s)) * '0' + s[2:]

能够跑通,进一步印证了OJ支持类型暗示。

最后发现这一段报了Runtime Error:

def bytelist_to_int(bytelist_: list[int]):
    out_ = 0
    for byte in bytelist_:
        out_ = out_ << 8 | byte
    return out_

其中最可疑的还是类型暗示:bytelist_: list[int]。所以联想到版本差异,去python官网上查说明文档了。看到3.9版本的python对类型暗示是这样讲的:

 而自3.5开始一直到3.8,对类型暗示是这样讲的:

 发现不同了吗?对于序列型数据类型(除str),以前的类型暗示要求首字母大写(List[type], Tuple[type], Dict[type1, type2]), 而从3.9开始,它改成只有小写了(list[type], tuple[type], dict[type1, type2]). 而OJ上python版本是3.6,我和室友的python版本都是3.9,因此不能复现OJ上的Runtime Error.

转来转去,发现问题还是在类型暗示上。。。

看来还是和OJ上python版本保持一致比较好。

最后索性删掉所有类型暗示,accepted。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值