Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 10, 2011 14:34:19

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

Странное поведение метода

Хочу реализовать работу с векторами. Создал модуль (space.py) и класс (vector). setdir и __init__ работают правильно, а вот add и sub как-то странно.

import math

class vector:
direct = [0, 0] # координаты конца вектора
def __init__ (self, direct = [0, 0], value = None):
self.setdir (direct, value)
def setdir (self, direct = [0, 0], value = None):
if value != None:
k = math.sqrt(direct[0] ** 2 + direct[1] ** 2) / value
self.direct[0] = direct[0] / k
self.direct[1] = direct[1] / k
else:
self.direct[0] = direct[0]
self.direct[1] = direct[1]
def add (self, vect):
self.direct[0] += vect.direct[0]
self.direct[1] += vect.direct[1]
def sub (self, vect):
self.direct[0] -= vect.direct[0]
self.direct[1] -= vect.direct[1]
Вот как это выглядит:

>>> from space import vector 
>>>
>>> x = vector([12, 14])
>>> y = vector([3, 4])
>>> y.add(x)
>>> y.direct
[6, 8]
>>> x.direct
[6, 8]



Офлайн

#2 Авг. 10, 2011 14:40:05

ZAN
От:
Зарегистрирован: 2007-06-10
Сообщения: 403
Репутация: +  10  -
Профиль   Отправить e-mail  

Странное поведение метода

class vector:
direct = [0, 0] # координаты конца вектора
Не путать с явой! )
Здесь direct - это атрибут класса, а нужно, чтобы был атрибут экземпляра.
Правильно так:
class vector:
def __init__(self, direct=None, value=None):
if direct:
self.direct = direct
else:
self.direct = [0, 0]
я вынес из дефолтовых значений не просто так - этот список создается один раз при создании _класса_, а не каждый раз при вызове конструктора, что вызовет забавные сайд эффекты, если direct не указан )



Офлайн

#3 Авг. 10, 2011 15:07:29

Isem
От:
Зарегистрирован: 2010-08-27
Сообщения: 447
Репутация: +  7  -
Профиль   Отправить e-mail  

Странное поведение метода

А если в классе реализовать функцию __iadd__ (inplace add):

class vector:
......
def __iadd__(self, vect):
self.direct[0] += vect.direct[0]
self.direct[1] += vect.direct[1]
return self
то можно писать так:
y += x



Офлайн

#4 Авг. 10, 2011 16:25:30

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

Странное поведение метода

Спасибо ZAN и Isem за помощь, но я так и не понял, что происходило-то. Можно по подробней?



Офлайн

#5 Авг. 10, 2011 18:02:48

Isem
От:
Зарегистрирован: 2010-08-27
Сообщения: 447
Репутация: +  7  -
Профиль   Отправить e-mail  

Странное поведение метода

Происходило вот что.
Переменная direct была объявленна как переменная класса, а не экземпляра класса. Это означает, что у всех экземпляров класса (в нашем случае это ‘x’ и ‘y’) она всегда одна и та же. То есть если мы ее меняем у ‘х’, она меняется и у ‘y’. После того, как вы написали y = vector(), значения вектора х стало таким же. А после того, как вы написали y.add(x), то получили вектор с координатами (3+3, 4+4).



Офлайн

#6 Авг. 10, 2011 21:58:35

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

Странное поведение метода

Тут может сходу не понятно, человеку не подготовленному, но в Python классы такие же объекты как экземпляры (в принципе), они не что-то виртуальное и существующее “на бумаге” лишь для компиляции. Классы можно создавать, изменять и сносить уже во время работы интерпретатора (собственно во время работы они и создаются, другого не дано, просто прозрачно, не руками). Так что то что у класса есть переменная, в том нет ничего странного (у класса ещё и методы есть, которые можно править во время работы :-).

..bw



Офлайн

#7 Авг. 10, 2011 22:46:58

atomAltera
От:
Зарегистрирован: 2011-07-27
Сообщения: 54
Репутация: +  0  -
Профиль   Отправить e-mail  

Странное поведение метода

а разве когда он к атрибуту self.direct присваивает значение, он не должен создаться для экземпляра, ведь что-бы создать/перезаписать атрибут класса, надо непосредственно класс.атрибут указать?



Офлайн

#8 Авг. 10, 2011 23:08:26

dimabest
От:
Зарегистрирован: 2009-02-12
Сообщения: 253
Репутация: +  0  -
Профиль   Отправить e-mail  

Странное поведение метода

atomAltera
а разве когда он к атрибуту self.direct присваивает значение, он не должен создаться для экземпляра
Он не присваивает значение атрибуту self.direct, а изменяет значение элементов списка.



Офлайн

#9 Авг. 10, 2011 23:21:42

atomAltera
От:
Зарегистрирован: 2011-07-27
Сообщения: 54
Репутация: +  0  -
Профиль   Отправить e-mail  

Странное поведение метода

ой, и правда. А я смотрел, смотрел, думал, что не так? Пардон



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version