我的课程模板在这里:
import sqlite3
class Patron(object):
#Let's set some basic attributes
attributes = { "patron_id" : None,
"name" : None,
"address" : None,
"phone" : None,
"email" : None,
"fee_balance" : None,
"fees_per_day" : None,
"books_checked_out" : [],
"books_overdue" : []}
def __init__(self):
#Create a empty instance
pass
def new(self, patron_id, name, address, phone, email):
#Create an instance with new values
self.attributes["patron_id"] = patron_id
self.attributes["name"] = name
self.attributes["address"] = address
self.attributes["phone"] = phone
self.attributes["email"] = email
def retrieve(self, patron_id):
#Connect to database and prepare patron id
self.attributes["patron_id"] = patron_id
patron_database = sqlite3.connect('patrons.db')
cursor = patron_database.cursor()
t = (str(patron_id),)
#Get data from database
cursor.execute("SELECT * FROM patrons WHERE id =?", t)
data = cursor.fetchone()
#Now close your database connection
patron_database.close()
#Parse tuple into attributes
self.attributes["name"] = data[1]
self.attributes["address"] = data[2]
self.attributes["phone"] = data[3]
self.attributes["email"] = data[4]
self.attributes["fee_balance"] = data[5]
self.attributes["fees_per_day"] = data[6]
self.attributes["books_checked_out"] = data[7]
self.attributes["books_overdue"] = data[8]
def save(self):
#Connect to the database
patron_database = sqlite3.connect('patrons.db')
cursor = patron_database.cursor()
#Compile the data into a list
attributes = []
for value in self.attributes.itervalues():
attributes.append(value)
#Insert the values and save them
cursor.execute("INSERT INTO patrons VALUES(?,?,?,?,?,?,?,?,?)", attributes)
patron_database.commit()
#Close the connection
patron_database.close()
然后我在这里有我的测试代码:
'''
Created on Feb 2, 2013
@author: Zach
'''
from Patron import Patron
zach = Patron()
braden = Patron()
zach.retrieve(1187277)
print zach.attributes
print braden.attributes
我的控制台说“zach”和“braden”实例都具有完全相同的属性,即使我没有为“braden”实例设置任何内容。如果我将某些内容分配给“braden”实例,那么它们都共享该实例的属性。
我认为这是与可变默认参数行为相关的问题,但我无法弄清楚我的问题。
答案 0 :(得分:6)
您已将attributes
设为class
级变量,因为dict
是可变的。在__init__
内移动它的定义,它应该有效。
class demo(object):
class_level = {'a': 0}
class_level_nm = 0
class_level2 = 0
def __init__(self, v):
self.instance_level = v
self.class_level['a'] += 1
self.class_level_nm += 1
demo.class_level2 += 1
def __str__(self):
return 'class level (mut): %d class level (unmut): %d instance level: %s class level2: %d' % (self.class_level['a'],
self.class_level_nm,
self.instance_level,
self.class_level2)
a = demo('a')
b = demo('b')
print a
print b
c = demo('c')
print a
print b
print c
给出:
class level (mut): 2 class level (unmut): 1 instance level: a class level2: 2
class level (mut): 2 class level (unmut): 1 instance level: b class level2: 2
class level (mut): 3 class level (unmut): 1 instance level: a class level2: 3
class level (mut): 3 class level (unmut): 1 instance level: b class level2: 3
class level (mut): 3 class level (unmut): 1 instance level: c class level2: 3
答案 1 :(得分:1)
这不是直接“可变默认参数”问题,因为根本没有默认函数参数。问题只是你实际上并没有在zach
和braden
上设置任何属性!
当您致电zach.retrieve(1187277)
时,retrieve
执行此
self.attributes["patron_id"] = patron_id
你似乎对这是如何工作有一些误解,所以让我们来看看Python将如何逐步评估这个陈述。
必要的第一步是查找self.attributes
。这首先在名为self
的{{1}}中查找属性,但没有这样的属性。
当读取属性时,这会回到查看attributes
的类(以及任何基类,但这里没有相关性)。因此,后退是在self
中查找名为attributes
的属性。这会成功并填充字典,因此该对象是查找的结果。
下一步是对查找结果执行“项目分配”操作。项目分配是Patron
语法的作用;在您的情况下,object[key] = value
是对象,self.attributes
是关键字,"patron_id"
是值。因此,最终将字典中的密钥patron_id
设置为"patron_id"
存储在person_id
类的attributes
属性中。
那么Patron
和print zach.attributes
显示相同的事情就完全不足为奇了。它们都没有print braden.attributes
属性,因此两者都会在类attributes
中找到attributes
属性。如果你通过分配给那个字典继续存储所有属性,那么显然在一个字体中做出的任何改变都会影响你从另一个字体中看到的内容。