如何创建两个同名但独立的SymPy Symbol对象?
SymPy自定义Symbol类同名实例覆盖属性的问题解决
你观察的没错,SymPy的Symbol类内部使用了对象缓存机制——当创建同名符号时,会返回已存在的实例,而不是新创建对象。所以第二次调用MySymbol('x', 200)时,拿到的是第一次创建的symbolx实例,随后覆盖了它的description属性,最终两个变量指向同一个对象,输出结果都是200。
方案1:禁用Symbol的缓存机制
修改自定义类的__new__方法,调用父类的__new__时传入cache=False参数,强制每次创建新实例:
from sympy import Symbol class MySymbol(Symbol): def __new__(cls, symbol, description): # 传入cache=False禁用缓存,每次生成新实例 obj = super().__new__(cls, symbol, cache=False) obj.description = description return obj symbolx = MySymbol('x', 100) symbolx2 = MySymbol('x', 200) symboly = MySymbol('y', 300) print(symbolx.description) # 输出100 print(symbolx2.description) # 输出200 print(symboly.description) # 输出300
优点:不改变SymPy默认的符号相等逻辑,后续符号运算不受影响;实现简单。
方案2:修改实例的相等性判断逻辑(谨慎使用)
如果需要保留缓存,但希望不同描述的同名符号被视为不同实例,可以重写__eq__和__hash__方法,将description纳入相等性判断的依据:
from sympy import Symbol class MySymbol(Symbol): def __new__(cls, symbol, description): obj = super().__new__(cls, symbol) obj.description = description return obj def __eq__(self, other): # 先判断是否为MySymbol实例,再同时比较符号名和描述 if isinstance(other, MySymbol): return super().__eq__(other) and self.description == other.description return super().__eq__(other) def __hash__(self): # 将符号名的哈希和描述的哈希组合作为实例的哈希值 return hash((super().__hash__(), self.description)) symbolx = MySymbol('x', 100) symbolx2 = MySymbol('x', 200) symboly = MySymbol('y', 300) print(symbolx.description) # 输出100 print(symbolx2.description) # 输出200 print(symboly.description) # 输出300 print(symbolx == symbolx2) # 输出False,视为不同符号
注意:该方案会改变SymPy默认的符号相等逻辑,可能导致后续符号运算中,同名但不同描述的符号无法被识别为同一个变量,仅适合不需要将这些符号视为同一变量的场景。
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

