2010-06-14 3 views
4

Я хотел бы переопределить __deepcopy__ для данного сопоставленного SQLAlchemy класса таким образом, чтобы он игнорировал любые атрибуты SQLA, но глубоко копировал все остальное, что является частью класса.Как я могу «переопределить» глубину в Python?

Я не очень-то знаком с тем, чтобы переопределять любые встроенные объекты Python, но у меня есть представление о том, чего я хочу.

Давайте просто сделаем очень простой класс User, который отображается с использованием SQLA.

class User(object): 
    def __init__(self, user_id=None, name=None): 
     self.user_id = user_id 
     self.name = name 

Я использовал dir() видеть, до и после того, как отображение, какие SQLAlchemy специфических атрибутов есть, и я нашел _sa_class_manager и _sa_instance_state.

Questions
Предоставлено те являются единственными, как бы я игнорирую, что при определении __deepcopy__?
Также есть ли какие-либо атрибуты, которые SQLA вводит в сопоставленный объект?


(я спросил это в предыдущем вопросе (как редактировать через несколько дней после того, как я выбрал ответ на главный вопрос, хотя), но я думаю, что я пропустил поезд там. Извиняюсь за это.)


Edit - Fixed code thanks to zifot's answer

Единственное, что я вылезла из документации Python является то, что вам нужно определить DeepCopy с memo в качестве дополнительного аргумента. После того, как крохотные немного покопаться я попытался это:

def __deepcopy__(self, memo): 
    dpcpy = self.__class__() 
    memo[id(self)] = dpcpy 
    for attr in dir(self): 
     if not attr.startswith('_'): 
      value = getattr(self, attr) 
      setattr(dpcpy, attr, copy.deepcopy(value, memo)) 
    return dpcpy 

Затем я создал экземпляр User как:

snake = User(913, 'Snake,S.') 

После этого я попробовал deepcopy операции, как:

snake_dc = copy.deepcopy(snake) 

... и snake_dc все еще имеет атрибуты SQLA в нем ...

Я все открыт, чтобы помочь, предложения и т. Д.

ответ

0

Я не эксперт по глубине, но из-за ошибки похоже, что вам нужен конструктор без параметров, который вызывает self.__class__() без параметров.

+0

К сожалению, то, что вы имеете в виду под "конструктор" без параметров? – PizzAzzra

+0

Извините. «__init__», который не требует переменных вне себя. См. Ответ zifot для примера. – mavnn

+0

То, что он имеет в виду, заключается в том, что функция User____ init__ («конструктор», хотя технически это не конструктор) принимает три аргумента: self, user_id и имя, но когда вы вызываете себя .__ class __(), вы передаете только первый один (неявно). – zifot

1

mavnn is right. Например попробуйте изменить инициализации Пользователя на:

def __init__(self, user_id = None, name = None): 
     self.user_id = user_id 
     self.name = name 

Что касается копирования сопоставляется экземпляры, я рекомендую читать this thread

+0

Спасибо. Изменен '__init__' для' User', но, к сожалению, 'snake_dc', похоже, не имеет атрибутов SQLA: S – PizzAzzra

+0

То есть какие? – zifot

+0

'_sa_class_manager', '_sa_instance_state' – PizzAzzra

0

Чтобы исключить SQLAlchemy столбцов и преобразованные атрибуты вы могли бы сделать что-то вдоль линий:

for attr in dir(self): 
    if not self._sa_class_manager.mapper.has_property(key): 
     ... 
1

Когда (глубокое) копирование, вы не должны звонить __init__, а вместо этого звоните __new__.

пример:

def __copy__(self): 
    cls = self.__class__ 
    newobject = cls.__new__(cls) 
    newobject.__dict__.update(self.__dict__) 
    return newobject 
+0

+1 Это объясняется комментарием Роба Юнга в: http://stackoverflow.com/questions/1500718/what-is-the-right-way-to-override-the-copy-deepcopy-operations-on-an -объект-в-р – ponadto