2013-07-03 3 views
1

У меня есть функциональный фрагмент кода, который работает отлично (в однопоточных окружающей среды)Python метод по умолчанию проблема инициализации аргумент в CherryPy

class SQLEngine(object): 
    def __init__(self, DB_PATH, referential_integrity=False): 
     self.path = DB_PATH 
     self.con = sqlite.connect(DB_PATH) 
     self.cur = self.con.cursor() 
     if referential_integrity: 
      self.executeUpdate('PRAGMA foreign_keys = ON') 


class EntityAdapter(object): 
    def __init__(self, database = SQLEngine('etc.db'): 
     self.db = database 

    def addFeature(self, feature_id, description): 
     self.db.executeUpdateAndCommit('INSERT INTO features (id, description) values (?, ?)', (feature_id,description)) 

adapter = EntityAdapter() 
adapter.addFeature(1, 'super feature') 

Однако в среде CherryPy я вижу очень интересные явления, которые я надеваю» У меня есть объяснение.

adapter = EntityAdapter() //Does not work 
adapter.addFeature(1, 'super feature') 

терпит неудачу с

SQLite объекты, созданные в потоке могут быть использованы только в том же самом объекте thread.The был создан в потоке ид ...

Я понимаю последствия использования sqlite в многопоточной среде ... но это означает, что в строке ниже значение по умолчанию назначается в другой теме

def __init__(self, database = SQLEngine('etc.db'): 

Самым простым способом исправить мой вопрос заключается в предоставлении явное значение Db

adapter = EntityAdapter(SQLEngine('etc.db')) //works 
adapter.addFeature(1, 'super feature') 

мне было интересно, как это возможно для значения по умолчанию рассчитывается в другом потоке?

+2

Еще одна жертва, в еще одном уникальном пути, из изменяемые по умолчанию Аргумент Trap: http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument ? rq = 1 –

ответ

2

В Python аргументы по умолчанию для функции привязаны при определении функции, а не при вызове функции. Это означает, что каждый раз, когда функция init вызывается с аргументом по умолчанию, используется тот же экземпляр объекта базы данных. Поэтому, если вы создадите несколько экземпляров EntityAdapter без аргументов, каждый отдельный экземпляр будет ссылаться на один и тот же объект базы данных. Что вы хотите сделать, так это следующее.

def __init__(self, database = None): 
    if database is None: 
     self.db = SQLEngine('etc.db') 
    else: 
     self.db = database 
+0

означает ли это, что значение по умолчанию оценивается во время загрузки класса? – bioffe

+1

@bioffe В то время создается объект функции, имеющий аргумент по умолчанию. Так что да. –

+0

Это связано с созданием функции. Поскольку это метод, это будет одновременно создание класса. Я отредактирую свой ответ, чтобы уточнить. –

Смежные вопросы