Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 5, 2011 10:06:41

Nolr
От:
Зарегистрирован: 2011-03-10
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

Добрый день.
Объясните, пожалуйста, почему при выходе из метода find в self оказывается атрибуты bar, а не foo?

class baz:
a = 1

def calc(self, value):
self.a = value
return copy.deepcopy(self)

def find(self):
foo = self.calc(1)
bar = self.calc(2)

self = copy.deepcopy(foo) # в self будет объект с a == 1
print self.a


x = baz()
print x.a

x.find()
print x.a # но тут a == 2
Можно обойти это так:
...
return foo

x = baz()
print x.a

y = x.find()
print x.a # но тут a == 2
print y.a
Но мне это кажется некрасивым решением.



Офлайн

#2 Дек. 7, 2011 00:04:20

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9973
Репутация: +  856  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

потому что self - локальная переменная метода



Офлайн

#3 Дек. 7, 2011 08:29:00

Nolr
От:
Зарегистрирован: 2011-03-10
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

А как изменить атрибуты экземпляра объекта baz, кроме явного копирования каждого из атрибутов объектов?
Есть ли ещё способы как можно вернуть из функции все атрибуты объекта, без описания каждого из атрибутов в return, и записать их в другой экземпляр объекта?

Вообще, мне не слишком понятен Ваш ответ. С помощью self я могу ссылаться на экземпляр класса. Так ведь? Но вот почему в объект x не копируется содержимое объекта foo? До копирования у объекта x и self в функции find() одинаковые адреса, а после копирования self перестёт ссылаться на x. Объясните свой ответ другими словами, пожалуйста.



Отредактировано (Дек. 7, 2011 11:14:24)

Офлайн

#4 Дек. 7, 2011 12:31:18

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9973
Репутация: +  856  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

Nolr
С помощью self я могу ссылаться на экземпляр класса.
self - это локальная переменная
когда метод вызывается, ей присваивается то, что в него передаётся (метод вызывается у экземпляра, он себя сам передаёт в свой метод)
когда делаешь внутри метода self = value, локальная переменная теряет своё прежнее значение и получает новое
если раньше там был экземпляр, то можно было через self обращаться к его свойствам и методам
а когда там стало value, то теперь там value, можешь через self обращаться к свойствам и методам value



Отредактировано (Дек. 7, 2011 12:34:55)

Офлайн

#5 Дек. 7, 2011 12:41:37

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9973
Репутация: +  856  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

>>> class A:
... def m(self):
... self.a = 1
... self = None
... print(self)
...
>>> obj = A()
>>> obj.m()
None
>>> obj.a
1
>>>



Офлайн

#6 Дек. 7, 2011 14:20:14

Nolr
От:
Зарегистрирован: 2011-03-10
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

Ага, теперь понятно почему self = copy.deepcopy(foo) создает новый объект. Мой промах, забыл о динамической типизации, хотел работать как с указателем. Спасибо за разъяснения.

А вот такой код хорош для копирования атрибутов экземпляра класса? Меня смущают объявления внутри класса на самого себя - foo = baz().

class baz:
def __init__(self):
self.a = 1
self.b = [2, 3]

def calc(self, value):
self.a = value
self.b[0] = value
return self.__dict__


def find(self):
foo = baz()
bar = baz()

foo = foo.calc(7)
bar = bar.calc(8)
self.__dict__ = foo
pass

x = baz()

x.find()
print x.a, x.b



Офлайн

#7 Дек. 7, 2011 14:58:11

Fibio
От:
Зарегистрирован: 2010-09-14
Сообщения: 74
Репутация: +  2  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

Как-то Вы совсем все запутали, self.__dict__ = foo - это вобще очень не тру, какова изначально задача? что должно происходить когда вызывается x.find()?



Офлайн

#8 Дек. 7, 2011 15:13:47

Nolr
От:
Зарегистрирован: 2011-03-10
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

calc() производит обработку атрибутов переданного экземпляра.
find() вызывает calc() с разными параметрами и ищет по заданным критериям результат. Грубо говоря, в find() вызывается calc() с параметрами от 1 до 10 и ищется минимальное значение результата вычислений. В переменной для хранения минимума нужно хранить все атрибуты объекта.

class baz:
def __init__(self):
self.a = 1
self.b = [2, 3]

def calc(self, value):
self.a = value
self.b[0] = value
return self.a + self.b[0]

def find(self):
min = calc(1)
i = 1
while i <= 10:
foo = calc(i)
if min > foo:
min = foo
i += 1
# а тут нужно в экземпляр объекта записать минимум
pass

x = baz()

x.find()



Отредактировано (Дек. 7, 2011 15:37:21)

Офлайн

#9 Дек. 7, 2011 16:47:23

Fibio
От:
Зарегистрирован: 2010-09-14
Сообщения: 74
Репутация: +  2  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

# -*- coding: utf-8 -*-
class baz(object):
def __init__(self, a=1, b=[2, 3]):
self.a = a
self.b = b

def calc(self, value):
self.a = value #не пойму зачем calc переопределяет атрибуты?
self.b[0] = value
return self.a + self.b[0]

def find(self):
min = self.calc(1)
for i in range(2,10):
foo = self.calc(i)
if min > foo:
min = foo
self.res = min
return self.res
#в экземпляр объекта неозможно записать число, м.б. присвоить атрибуту объекта?
#и возвращать при использовании принт:

def __repr__(self):
try:
return str(self.res)
except AttributeError:
return str(super(baz, self).__repr__())

if __name__ == '__main__':
x = baz()
print x
x.find()
print x



Отредактировано (Дек. 7, 2011 16:48:31)

Офлайн

#10 Дек. 8, 2011 09:51:17

Nolr
От:
Зарегистрирован: 2011-03-10
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Копирование объектов класса и deepcopy

# -*- coding: utf-8 -*-
class baz(object):
def __init__(self, a=1, b=[2, 3]):
self.a = a
self.b = b
# на деле тут около 20 атрибутов

def calc(self, value):
self.a = value # этими выражениями я заменил длинные расчеты, производимые с атрибутами объекта
self.b[0] = value
return self.a + self.b[0] # я бы хотел, что бы тут возвращался некий объект, в котором будет
# храниться a, b и куча других атрибутов, в том числе и минимум.

# функция ищет нужный минимум, а потом дальше будет идти другая обработка с этим минимумом и
# атрибутами, которые этот минимум образовывают
# Т.е. мне нужен не только сам результат, но и все атрибуты, которые учавствовали в вычислении результата
# Можно хранить номер итерации, при которой был получен минимум, и потом произвести эти вычисления
# заново, но я решил: а почему бы не хранить все нужное в объекте
def find(self):
min = self.calc(1) #
for i in range(2,10):
foo = self.calc(i)
if min > foo:
min = foo
self.res = min
return self.res
...



Отредактировано (Дек. 8, 2011 09:55:10)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version