为何random.choice选择结果严重失衡?技术咨询
问题分析与解决方案
这个问题的核心是你不小心修改了实例的持久化属性self.l,而且在每次调用get()方法时反复添加e和f,导致它们在候选列表中的占比越来越高,最终几乎垄断了随机选择结果。
问题根源拆解
我们一步步看代码的执行逻辑:
- 初始化
a = A("+abcd")后,self.l被设置为["a", "b", "c", "d"],这一步是正常的。 - 重点看
get()方法的实现:def get(self, l): rt = self.l if self.include: rt += l return choice(rt)rt = self.l这行是引用赋值,不是创建新列表。也就是说rt和self.l指向内存中的同一个列表对象。- 当执行
rt += l时,因为列表是可变对象,这个操作会直接修改原列表(也就是self.l),而不是创建新的列表。
所以第一次调用a.get(["e","f"])后,self.l变成了["a","b","c","d","e","f"];第二次调用时,又往里面追加了["e","f"],变成["a","b","c","d","e","f","e","f"];循环10万次后,self.l里e和f的数量已经达到几十万级,而a/b/c/d始终只有各1个,随机选中它们的概率自然微乎其微。
修复方案
只需要在get()方法中创建self.l的副本,避免修改原属性即可。修改后的get()方法如下:
def get(self, l): rt = list(self.l) # 或者用 self.l.copy(),创建原列表的独立副本 if self.include: rt += l return choice(rt)
这样每次rt都是一个全新的列表,修改它不会影响self.l,每次随机选择的候选列表都是固定的["a","b","c","d","e","f"],10万次循环后,各个元素的分布就会接近你预期的均匀状态。
补充提示
这是Python中可变对象(列表、字典、集合等)的常见陷阱:赋值操作传递的是对象引用而非副本,修改赋值后的变量会直接影响原对象。如果需要操作对象的副本,一定要显式创建(比如list(obj)、obj.copy()等方式)。
内容的提问来源于stack exchange,提问作者GT 77
相关产品推荐
相关产品推荐

