2013-02-02 51 views
0

我有我的類模板的位置:Python對象的多個實例表現得像同一個實例

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 

我的控制檯說,這兩個儘管我沒有給「braden」實例設置任何東西,但「zach」和「braden」實例具有完全相同的屬性。如果我爲「braden」實例指定了某些內容,那麼它們都共享該實例的屬性。

我認爲這是一個有關可變默認參數行爲的問題,但我無法弄清楚我的問題。

回答

6

您已取得attributes a class水平變量,因爲dict s是可變的。將其定義在__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 
+0

是的是的!謝謝! – Zazzalicious

1

這不是直接的「可變默認參數」的問題,因爲你沒有函數默認參數都沒有。問題在於你根本沒有在zachbraden上設置任何屬性!

當你調用zach.retrieve(1187277)retrieve執行該

self.attributes["patron_id"] = patron_id 

你似乎有關於如何工作的一些誤解,所以讓我們經歷Python會如何評價一步這一說法一步。

需要的第一步是查找self.attributes。首先在self中查找名爲attributes的屬性,但不存在此屬性。

當讀取一個屬性,然後回落到self(和任何基類,但這裏不相關)。所以後退就是在Patron中尋找名爲attributes的屬性。這成功並鰭字典,以便對象是查找的結果。

下一步是對查找結果執行「項目分配」操作。項目分配是object[key] = value語法的作用;在你的情況下,self.attributes是對象,"patron_id"是關鍵,而patron_id是值。因此,這最終將字典中的密鑰"patron_id"設置爲person_id,該字典被存儲在Patron類別attributes屬性中。

因此,print zach.attributesprint braden.attributes顯示相同的結果是完全不令人驚訝的。它們都沒有attributes屬性,所以它們都會在類Patron中找到attributes屬性。如果你通過分配字典來保存所有的屬性,那麼顯然任何一個變化都會影響你從另一箇中看到的東西。