背景:在做一个目标检测的项目。要对每张图片生成预测的mAP等指标。
def run():
for batch_i, (im, targets, paths, shapes) in enumerate(pbar):
...
for si, pred in enumerate(preds):
labels = targets[targets[:, 0] == si, 1:]
nl, npr = labels.shape[0], pred.shape[0]
...
#生成单张图片测试结果的脚本
single(stats_temp, plots, save_dir, names, nc, verbose, seen, training, npr, pred, id_string)
出现的问题就是:pred为第二个for循环内的变量,但是我也想在第二个for循环外用到,应该怎样声明呢?
解决方法:
- 使用关键词
global生成全局变量。
def run():
for batch_i, (im, targets, paths, shapes) in enumerate(pbar):
...
for si, pred in enumerate(preds):
global pred
labels = targets[targets[:, 0] == si, 1:]
nl, npr = labels.shape[0], pred.shape[0]
...
#生成单张图片测试结果的脚本
single(stats_temp, plots, save_dir, names, nc, verbose, seen, training, npr, pred, id_string)
弊端:代码难以维护。
- 将局部变量pred在for循环外声明,值赋为
None。
def run():
for batch_i, (im, targets, paths, shapes) in enumerate(pbar):
...
pred=None
for si, pred in enumerate(preds):
labels = targets[targets[:, 0] == si, 1:]
nl, npr = labels.shape[0], pred.shape[0]
...
#生成单张图片测试结果的脚本
single(stats_temp, plots, save_dir, names, nc, verbose, seen, training, npr, pred, id_string)
弊端:设置为None,None是Python中的一种特殊数据类型,表示变量没有值。当pred到被用的时候都没有被赋进去值,那么就会报错。
针对于变量报错,但是又希望整个程序运行完。可以使用异常处理来捕捉异常:
注:要用try包住pred变量整个的使用区域。
def run():
for batch_i, (im, targets, paths, shapes) in enumerate(pbar):
...
try:
pred=None
for si, pred in enumerate(preds):
labels = targets[targets[:, 0] == si, 1:]
nl, npr = labels.shape[0], pred.shape[0]
...
#生成单张图片测试结果的脚本
single(stats_temp, plots, save_dir, names, nc, verbose, seen, training, npr, pred, id_string)
except Exception:
print("有误")
- 将局部变量pred在for循环外声明,值赋为该变量的类型下的0值/空值。
第一步:获取该变量类型。
使用type()函数可以获取任何数据的类型。
print(type(pred))
第二步:获取该变量的形状。
#获取numpy类型的形状
my_array = np.zeros((3, 4))
print(my_array.shape)
#获取tensor类型的形状
my_tensor = torch.zeros(3, 4)
print(my_tensor.shape)
#获取list类型的形状
my_list = [[[2,3,4],[6,7,8]],[[2,3,0],[6,7,9]]]
def get_shape(lst):
shape = []
while isinstance(lst, list):
shape.append(len(lst))
lst = lst[0]
return tuple(shape)
print(get_shape(my_list)) # Output: (2, 2, 3)
第三步:生成0/空的该变量
#生成numpy类型的0/空变量
my_array1 = np.zeros((3, 4))
my_array2 = np.ones((3, 4))
my_array3 = np.empty((3, 4))
#生成tensor类型的0/1空变量
my_tensor1 = torch.zeros(3, 4)
my_tensor2 = torch.ones(3, 4)
my_tensor3 = torch.empty(3, 4)
#生成list类型的空变量
my_list = []
最终:
def run():
for batch_i, (im, targets, paths, shapes) in enumerate(pbar):
...
try:
pred=torch.zeros((3,4))
for si, pred in enumerate(preds):
labels = targets[targets[:, 0] == si, 1:]
nl, npr = labels.shape[0], pred.shape[0]
...
#生成单张图片测试结果的脚本
single(stats_temp, plots, save_dir, names, nc, verbose, seen, training, npr, pred, id_string)
except Exception:
print("有误")
总结:通过自己写了一个脚本,对于代码块内的变量怎样在代码块外声明,有了一个经验:即在代码块外无类型声明
None,或有类型声明0/1/空(获取类型→获取形状)。这里或许还有很多不足,比如这个变量形状可能是变化的,那么万一经下面的语句该变量都没被赋值上,就会报错,个人为了针对这种情况,往往用try..except..来捕捉的。这里还请各位大佬给我指正!