You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python类状态中的可变对象:密码生成器类列表意外修改解析

Python类列表引用导致的意外修改问题解析

问题场景

使用以下密码生成器类创建不同强度的密码时,发现类变量SAMPLES中的"letters"列表被意外修改:

import re
import random
from string import ascii_letters, punctuation
from copy import copy

class Password:
    
    SAMPLES = {
        "letters": list(ascii_letters),
        "numbers": list(range(10)),
        "punctuation": list(punctuation)
    }
    
    DEFAULT_SETTINGS = {
        "low": 8,
        "mid": 12,
        "high": 16
    }
    
    @classmethod
    def show_input_universe(cls):
        return cls.SAMPLES
    
    
    def _generate_password(self):
        
        population = self.SAMPLES["letters"]
        length = self.length or self.DEFAULT_SETTINGS.get(self.strength)
        
        if self.strength == "high":
            population += self.SAMPLES["numbers"] + self.SAMPLES["punctuation"]
        elif self.strength == "mid":
            population += self.SAMPLES["numbers"]
        else:
            pass
        
        self.password = "".join(map(str, random.choices(population, k=int(length))))
    
    
    def __init__(self, strength="mid", length=None):
        self.strength = strength
        self.length = length
        
        self._generate_password()

当生成高强度/中等强度密码后,再生成低强度密码时,结果会包含数字或符号;调用show_input_universe()也能看到原"letters"列表被追加了其他类型的字符。

核心原因解析

问题的关键在于可变对象的引用特性和列表+=操作的本质:

  1. 引用指向同一对象:population = self.SAMPLES["letters"]语句中,self.SAMPLES["letters"]是类变量存储的列表对象(可变类型),赋值操作只是让population变量指向这个同一个列表对象,并没有创建新的副本。
  2. +=是原地修改操作:对于列表这类可变对象,+=运算符等价于调用list.extend()方法,它会直接在原列表对象上追加元素,而不是创建一个新的列表重新赋值给population。

因此,当执行population += self.SAMPLES["numbers"]这类代码时,实际是在修改self.SAMPLES["letters"]指向的原列表对象——也就是类变量SAMPLES里的"letters"列表,所有后续实例都会共享这个被修改后的列表。

解决方案验证

使用copy模块创建列表副本,让population指向一个新的列表对象:

population = copy(self.SAMPLES["letters"])

此时population是原"letters"列表的独立副本,后续的+=操作只会修改这个副本,不会影响类变量中的原列表,从而避免不同强度密码的字符池互相干扰。

内容的提问来源于stack exchange,提问作者maosi100

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:07:04