1

我在这里有我的课程模板:

 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”实例分配了一些东西,那么它们都共享该实例的属性。

我认为这是与可变默认参数行为有关的问题,但我无法弄清楚我的问题。

4

2 回答 2

7

您已经创建了attributes一个class级别变量,并且因为dicts 是可变的。将它的定义移到里面,__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
于 2013-02-02T23:03:33.220 回答
1

这不是直接的“可变默认参数”问题,因为您根本没有默认函数参数。问题在于您实际上zach并没有设置任何属性braden

当你调用时zach.retrieve(1187277)retrieve执行这个

self.attributes["patron_id"] = patron_id

您似乎对它的工作原理有一些误解,因此让我们逐步了解 Python 将如何评估此语句。

第一步是查找self.attributes. self这首先在named中寻找一个属性attributes,但没有这样的属性。

当读取一个属性时,这会回退到查看self和任何基类,但这在这里不相关)。所以回退是寻找一个名为attributesin的属性Patron。这成功并找到了一个字典,因此该对象是查找的结果。

下一步是对查找的结果执行“项目分配”操作。项目分配是object[key] = value语法的作用;在您的情况下self.attributes是对象,"patron_id"是键,patron_id是值。因此,这最终将键设置"patron_id"为存储在class的属性中person_id 的字典中attributesPatron

So then it's completely unsurprising that print zach.attributes and print braden.attributes show the same thing. Neither of them has an attributes attribute, so both are going to find the attributes attribute in the class Patron. And if you keep storing all your attributes by assigning to that dictionary, then obviously any change made in one will affect what you see from the other.

于 2013-02-02T23:27:33.703 回答