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

「braden」インスタンスに何も設定していないにもかかわらず、「zach」インスタンスと「braden」インスタンスの両方がまったく同じ属性を持っているとコンソールに表示されます。「braden」インスタンスに何かを割り当てると、両方がそのインスタンスのプロパティを共有します。

変更可能なデフォルト引数の動作に関連する問題だと思いますが、私の問題を理解できません。

4

2 に答える 2

7

s が変更可能であるためattributesclassレベル変数を作成しました。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
于 2013-02-02T23:03:33.220 に答える
1

デフォルトの関数引数がまったくないため、これは直接「可変のデフォルト引数」の問題ではありません。問題は、実際には属性をまったく設定していないということzachですbraden

を呼び出すとzach.retrieve(1187277)、これをretrieve実行します

self.attributes["patron_id"] = patron_id

これがどのように機能するかについていくつかの誤解があるように思われるので、Pythonがこのステートメントを段階的に評価する方法を見ていきましょう。

必要な最初のステップは、ルックアップself.attributesです。これは最初にselfnamedattributesで属性を探しますが、そのような属性はありません。

属性を読み取るとき、これはのクラスself(および任意の基本クラスですが、ここでは関係ありません)の検索にフォールバックします。attributesしたがって、フォールバックはで指定された属性を探すことですPatron。これは成功し、辞書を検索するため、オブジェクトはルックアップの結果になります。

次のステップは、ルックアップの結果に対して「アイテム割り当て」操作を実行することです。アイテムの割り当ては、object[key] = value構文が行うことです。あなたの場合self.attributesはオブジェクトで"patron_id"あり、キーでありpatron_id、値です。したがって、これは、クラスの属性に格納されているディクショナリに"patron_id"キーを設定することになります。person_id attributesPatron

ですから、それはまったく驚くべきことではなく、同じことprint zach.attributesを示しています。print braden.attributesどちらにも属性がないため、どちらもクラスで属性attributesを検索します。そして、その辞書に割り当ててすべての属性を保存し続けると、明らかに、一方に加えられた変更は、もう一方から見えるものに影響を与えます。attributesPatron

于 2013-02-02T23:27:33.703 に答える