python – 模型中的SQLAlchemy自定义本地属性
我定义了一个简单的模型,并在类中添加了一些非SQL相关的属性.
如果属性是int或string类型的东西正在工作.但如果它是字典或列表类型,那么神奇地在模型类的所有不同实例上使用相同的列表. 例: # Sample model class class TestClass(Base): # SQL Mappings __tablename__ = 'test1' pid = Column("id",Integer,primary_key=True) name = Column('name',String) # Non SQL related attributes works_var = 0 works_not_var = [] # ... 在查询处理检索到的TestClass实例之后的其他地方 my_test_class.works_not_var.append("testval1") my_test_class2.works_not_var.append("testval2") 不知何故,两个附加值最终都在同一个列表中: print id(my_test_class.works_not_var) print id(my_test_class2.works_not.var) 我的是一样的.但它适用于“works_var”.我有不同的. 解决方法
这绝对与SQLAlchemy无关,是标准的Python行为.问题的原因与Python处理类型和解析事物的方式有关.考虑这个有趣的例子:
class A(object): print "Hello" print "A is now defined" a = A() print "I now have an instance of A" 这当然完全没用,但在执行时,观察打印顺序: Hello A is now defined I now have an instance of A 你有没有想到这个? 简单解决方案 # Sample model class class TestClass(Base): # SQL Mappings __tablename__ = 'test1' pid = Column("id",String) # ... def __init__(self): self.works_var = 0 self.works_not_var = [] 经验法则:将__init__中的默认参数放在类级别上. 说明 可以按顺序进行更彻底的解释:为什么会出现问题?我不会详细介绍Python如何处理变量.在eevee的Python FAQ: Passing文章中有一个简洁的解释.此外,这里有一个很好的解释:Other languages have “variables”. 有了这些知识并从上面的例子中我们现在知道何时执行语句works_not_var = []:导入它的那一刻(或者脚本被启动).我们也知道为什么这是一个问题:像list这样的对象是可变的,当你改变它时Python不会移动它的“标记”:而是你创建了一个实例变量.更常见的是,这个问题在函数默认参数上被注意到(并且更容易解释).考虑这个问题:“Least Astonishment” in Python: The Mutable Default Argument.它解释了它是如何产生的.在一个简洁的例子中: def f(a=[]): if len(a) == 0: print "Oh no,list is empty" a.append(1) f() print "Function executed first time" f() print "Function executed second time" 并输出: Oh no,list is empty Function executed first time Function executed second time 该列表是在解析它们时创建的,而不是执行时间.另一个如何失败并产生愚蠢问题的例子: from datetime import datetime from time import sleep def f(time=datetime.now()): print time f() sleep(1) f() f(datetime.now()) 因此,您创建了一个函数,该函数获得默认为当前时间的时间.好吧,不是那么多.它默认为程序启动的时间,但不是当前时间.如果你运行它你会得到: 2013-08-20 16:14:29.037069 2013-08-20 16:14:29.037069 2013-08-20 16:14:30.038302 但是你会期望第二次和第三次几乎相等而且在“第二”级别没有差别.问题再次出现:默认参数datetime.now()在解析函数未执行时执行. 解决方案 为此,还有一个简单的解决方案(虽然我可能会说我觉得它不像我想的那样漂亮): def f(now=None): if now is None: now = datetime.now() 我希望这个解释有所帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |