Python使用list[Individual]做类型注解报TypeError解决方法
报错原因
报错TypeError: 'type' object is not subscriptable是因为你使用的Python版本低于3.9,在Python3.9之前,内置的list类型不支持直接通过[]传入泛型参数作为运行时的类型标注,解释器执行到list[Individual]时会尝试对list类型做下标取值,自然抛出类型错误。
修复方案
有两种兼容方案,选一种即可:
- 方案1(改动最小,适配Python3.7+):在代码文件最开头加入
from __future__ import annotations,该语句会将所有类型注解延迟为字符串形式存储,不会在运行时执行注解解析,原函数的类型标注写法不需要任何修改就能正常运行。 - 方案2(适配所有Python3版本):从标准库
typing模块导入泛型类List,将函数参数和返回值处的list[Individual]全部替换为List[Individual]。
修复后完整可运行代码
以下代码同时修复了原代码里的不规范写法(原代码中new_individuals先存储新个体数量的整数,后续又被赋值为个体列表,且两层循环都用i作为迭代变量容易引发逻辑混淆):
# 选方案1就保留这行导入,不需要修改注解写法 from __future__ import annotations import random import numpy as np # 你自定义的Individual类保留原有实现即可 class Individual: def get_sharpe(self): # 保留原有方法实现 pass @classmethod def create_random(cls): # 保留原有方法实现 pass def selection_rank_with_population_replacement_elite( population: list[Individual], elite_size=0.1, new_pop=0.2 ) -> list[Individual]: sorted_individuals = sorted(population, key=lambda ind: ind.get_sharpe(), reverse=True) pop_total = len(sorted_individuals) best_n_individuals = int(np.floor(pop_total * elite_size)) new_individuals_count = int(np.floor(pop_total * new_pop)) rank_distance = 1 / pop_total ranks = [(1 - i * rank_distance) for i in range(pop_total)] ranks_sum = sum(ranks) selected = sorted_individuals[:best_n_individuals] for _ in range(pop_total - best_n_individuals - new_individuals_count): shave = random.random() * ranks_sum rank_sum = 0 for idx, ind in enumerate(sorted_individuals): rank_sum += ranks[idx] if rank_sum > shave: selected.append(ind) break new_individuals = [Individual.create_random() for _ in range(new_individuals_count)] selected.extend(new_individuals) return selected
如果选方案2,就把开头的future导入替换为from typing import List,再把两处list[Individual]替换为List[Individual]即可。
内容的提问来源于stack exchange,提问作者Kquek
相关产品推荐
相关产品推荐

