Python小坑—数据结构类型或边界错误
Python小坑—数据结构类型或边界错误

Python小坑—数据结构类型或边界错误

数据结构或者边界错误时候,直接报错而不是有其他的机制来避免错误影响。

严格来说不算一个坑,只能说是规范性问题。

Python是动态类型语言:

  • 不要求提前声明变量类型;
  • 不校验访问的的key是否存在;
  • 不检测list的边界;
  • 不会在编译阶段帮忙报错;

这导致一个问题,就是python经常运行到具体的某行代码时候才会报错。

d = {"name":"shen"}
print(d["age"])
Traceback (most recent call last):
  File "<input>", line 1, in <module>
KeyError: 'age'

arr = [1,2,3]
print(arr[10])
Traceback (most recent call last):
  File "<input>", line 1, in <module>
IndexError: list index out of range
print(arr["x"])
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: list indices must be integers or slices, not str

data = {"user": {"profile": {"phone": "123"}}}
print(data["user"])
{'profile': {'phone': '123'}}
print(data["user"]["address"]["city"])
Traceback (most recent call last):
  File "<input>", line 1, in <module>
KeyError: 'address'

解决方案只能是多注意,三个思路:类型注解、单元测试、mypy静态检查。

(1)类型注解

在代码里写清楚这个变量应该是什么类型,”->”,函数返回类型注解,就是声明这个函数应该返回什么类似数据,当然不强制。”:”,参数类型注解,则表示这个参数应该是字典,当然也不强制。这个工具能够使一些静态工具提前发现问题,在大型项目里提升代码的可读性。

def get_age(user: dict) -> int:
    return user["age"]
print(get_age(user))

user = {"age":10,"name":"wang"}
print(get_age(user))
10
user2 = {"age":20,"name":"zhang"}
print(get_age(user2))
20

这个之前项目代码里看到过很多次,每次都吐槽md写个代码怎么折腾那么复杂,现在发现了,原来都是有用的……

(2)单元测试

就是写测试用例,确保函数不会再实际运行时爆炸。assert就是python自带的断言语句【assert 条件表达式, ”报错信息“】。如果条件为True,什么都不做,如果条件为False,抛出AssertionError,就知道是这儿出了问题。

def test_get_age():
	user = {"age": 20} 
	assert get_age(user) == 20

(3)mypy静态检查(static type checking)

安装:pip install mypy
在终端执行:mypy test.py
很有意思的是第一次mypy没有指出错误,似乎因为太宽松了。

# test.py测试文件
def add(x: int, y: int) -> int:
    return x + y

def main():
    result = add("10", 20)  # 故意写错:传了字符串
    print(result)
main()

# 控制台:
(hellopython) PS C:\> cd .\Users\13989\Desktop\
(hellopython) PS C:\Users\13989\Desktop> mypy test.py
Success: no issues found in 1 source file
(hellopython) PS C:\Users\13989\Desktop> mypy test.py --strict 
test.py:4: error: Function is missing a return type annotation  [no-untyped-def]
test.py:4: note: Use "-> None" if function does not return a value
test.py:5: error: Argument 1 to "add" has incompatible type "str"; expected "int"  [arg-type]
test.py:8: error: Call to untyped function "main" in typed context  [no-untyped-call]
Found 3 errors in 1 file (checked 1 source file)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注