Игорь
Авг. 10, 2011 14:34:19
Хочу реализовать работу с векторами. Создал модуль (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]
ZAN
Авг. 10, 2011 14:40:05
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 не указан )
Isem
Авг. 10, 2011 15:07:29
А если в классе реализовать функцию __iadd__ (inplace add):
class vector:
......
def __iadd__(self, vect):
self.direct[0] += vect.direct[0]
self.direct[1] += vect.direct[1]
return self
то можно писать так:
Игорь
Авг. 10, 2011 16:25:30
Спасибо ZAN и Isem за помощь, но я так и не понял, что происходило-то. Можно по подробней?
Isem
Авг. 10, 2011 18:02:48
Происходило вот что.
Переменная direct была объявленна как переменная класса, а не экземпляра класса. Это означает, что у всех экземпляров класса (в нашем случае это ‘x’ и ‘y’) она всегда одна и та же. То есть если мы ее меняем у ‘х’, она меняется и у ‘y’. После того, как вы написали y = vector(), значения вектора х стало таким же. А после того, как вы написали y.add(x), то получили вектор с координатами (3+3, 4+4).
bw
Авг. 10, 2011 21:58:35
Тут может сходу не понятно, человеку не подготовленному, но в Python классы такие же объекты как экземпляры (в принципе), они не что-то виртуальное и существующее “на бумаге” лишь для компиляции. Классы можно создавать, изменять и сносить уже во время работы интерпретатора (собственно во время работы они и создаются, другого не дано, просто прозрачно, не руками). Так что то что у класса есть переменная, в том нет ничего странного (у класса ещё и методы есть, которые можно править во время работы :-).
..bw
atomAltera
Авг. 10, 2011 22:46:58
а разве когда он к атрибуту self.direct присваивает значение, он не должен создаться для экземпляра, ведь что-бы создать/перезаписать атрибут класса, надо непосредственно класс.атрибут указать?
dimabest
Авг. 10, 2011 23:08:26
atomAltera
а разве когда он к атрибуту self.direct присваивает значение, он не должен создаться для экземпляра
Он не присваивает значение атрибуту self.direct, а изменяет значение элементов списка.
atomAltera
Авг. 10, 2011 23:21:42
ой, и правда. А я смотрел, смотрел, думал, что не так? Пардон