Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 26, 2012 11:51:50

vault
Зарегистрирован: 2012-06-21
Сообщения: 52
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос про классы.

FishHook
b в твоём коде - аттрибут класса. Чтобы он стал аттрибутом объекта его нужно определять внутри метода.

О, как я долго заблуждался Спасибо. А почему a работает так странно? Он ведь тоже аттрибут класса?

Офлайн

#2 Июнь 26, 2012 11:53:50

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Вопрос про классы.

Информация для размышлений.

class A(object):
	   a = 0
	   
class B(object):
	   b = []
	   
a=A()
a1=A()
a.a=4
b=B()
b1=B()
b.b=[1,2,3]
print a.a
print a1.a
print b.b
print b1.b
Что изменится, если в методе мы объявим еще по одному такому же атрибуту?
правильно, при вызове атрибута будет вызываться атрибут объекта.

def __init__(self):
    self.b.append(1)
Здесь ты явно обращаешься к атрибуту класса, так как b нигде ранее в объекте не определен.



Офлайн

#3 Июнь 26, 2012 12:01:40

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Вопрос про классы.

vault
А почему a работает так странно? Он ведь тоже аттрибут класса?
Наверное поэтому
a=3
print hash(a)
a+=1
print hash(a)



Офлайн

#4 Июнь 26, 2012 12:03:09

vault
Зарегистрирован: 2012-06-21
Сообщения: 52
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос про классы.

По поводу информации для размышлений: судя по проверенному мной выше, b и b1 будут содержать одинаковые списки, а и а1 - разные переменные. Ну а почему?)

 def __init__(self):
    self.b.append(1)

Так я обращаюсь к self.b ведь. self - экземпляр класса, т.е. объект, нет разве? И почему, во имя Зевса, это по-разному работает для списков и числовых переменных?

Офлайн

#5 Июнь 26, 2012 12:13:52

vault
Зарегистрирован: 2012-06-21
Сообщения: 52
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос про классы.

vault
А почему a работает так странно? Он ведь тоже аттрибут класса?
Наверное поэтому
a=3
print hash(a)
a+=1
print hash(a)

А можете пояснить?)

Офлайн

#6 Июнь 26, 2012 12:17:37

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Вопрос про классы.

vault
По поводу информации для размышлений: судя по проверенному мной выше, b и b1 будут содержать одинаковые списки, а и а1 - разные переменные. Ну а почему?)

 def __init__(self):
    self.b.append(1)

Так я обращаюсь к self.b ведь. self - экземпляр класса, т.е. объект, нет разве? И почему, во имя Зевса, это по-разному работает для списков и числовых переменных?
Нормально все работает
class B():
   b=[]
   def __init__(self):
     self.b=[1,2,3]
b=B()
b1=B()
b.b=[0,0,0]
print b.b
print b1.b
print B.b
class A():
   a=0
   def __init__(self):
     self.a=9
a=A()
a.a=88
a1=A()
print a.a
print a1.a
print A.a



Отредактировано FishHook (Июнь 26, 2012 12:18:06)

Офлайн

#7 Июнь 26, 2012 12:23:51

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Вопрос про классы.

vault
vault
А почему a работает так странно? Он ведь тоже аттрибут класса?
Наверное поэтому
a=3
print hash(a)
a+=1
print hash(a)

А можете пояснить?)
Объекты в Питоне бывают двух разновидностей - изменяемые и неизменяемые. Списки, например - объекты изменяемые, их содержимое и длину можно менять. Поскольку ключами словарей могут быть только неизменяемые объекты, в Питоне есть специальный тип неизменяемых списков - кортежи. Числа, естественно, объекты неизменяемые. Также неизменяемыми являются строки, в отличии от многих других языков программирования. Хотя классы, написанные программистами, порождают изменяемые объекты, у программиста есть возможность написать класс, экземпляры которого могут быть ключами словаря.
Адресной арифметики в Питоне нет. Вообще. Поэтому разименовать нулевой указатель просто невозможно. Ссылки (указатели) в Питоне есть, но манипулирование ими осуществляется прозрачно для программиста. В действительности все переменные в Питоне являются ссылками на объекты; поэтому, например, запись a = b означает “в переменную a скопировать ссылку из переменной b”. Также списки и словари хранят не объекты, а ссылки на объекты. Присваивание и разыменование ссылок производится автоматически.
Каждый объект в Питоне хранит счетчик ссылок, и при таком копировании ссылки этот счетчик увеличивается. Счетчик же ссылок того объекта, на который переменная a указывала раньше - уменьшается. Когда счетчик достигает 0, объект считается неиспользуемым, для него вызывается деструктор (если это экземпляр класса с деструктором), и память объекта освобождается.
Такой механизм называется “синхронной сборкой мусора со счетчиком ссылок”. Помимо него, в Питоне есть асинхронный сборщик мусора, достоинство которого в том, что он умеет распознавать циклические ссылки и очищать объекты, на которые нет других ссылок (не из цикла). (Пример циклических ссылок: l=; l.append(l))
Рассмотрим поподробнее питоновские ссылки. Создадим список и присвоим его (на самом деле присвоим ссылку на него) в переменную a: a = . Теперь присвоим ссылку из a в переменную b: a = b. Изменим список, на который ссылается a, скажем, добавим в него содержимое другого списка: a += . На какой список ссылается переменная b? На тот же, что и a - на список из 4 элементов. Происходит это потому, что b все еще хранит ссылку на тот же список, что и a. А теперь присвоим в a новый список: a = . Что теперь будет в b? А все тот же список из 4 элементов. Присваивание в a разорвало связь между a и b. В переменной a теперь ссылка на новый список, а в переменной b все та же ссылка на тот же список.
Если a - переменная, хранящая ссылку на список, и присваивание b = a копирует только ссылку на тот же список, то можно ли скопировать сам список? Короткий ответ - да, можно. Но не все так просто. Ведь и сам список хранит не объекты, а ссылки на объекты. Должны ли копироваться эти ссылки или должны быть продублированы и сами объекты? Питон дает два ответа на этот вопрос: можно сделать и так, и эдак. Первый вариант копирования называется “поверхностным”, второй - “глубоким” копированием. Глубокое копирование учитывает циклические ссылки. Классы, написанные программистом, могут определять методы, участвующие в копировании, тем самым “помогая” процессу копирования, для того чтобы не включать в копирование лишней информации.
Манипуляции с неизменяемыми объектами осуществляются путем создания новых объектов. Например, если в строке надо заменить символ, исходная строка разбивается на две подстроки, и из них (плюс новый символ) создается новая строка. Если в переменной a ссылка на цело число, то в результате операции a += 1 в a окажется ссылка на новое число.



Офлайн

#8 Июнь 26, 2012 13:36:41

vault
Зарегистрирован: 2012-06-21
Сообщения: 52
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос про классы.

Спасибо, я знал про неизменяемые и изменяемые объекты.
Сейчас попытаюсь переформулировать вопрос:

>>> class B(object):
	b = []
	def __init__(self): 
		self.b.append(1) 
		
>>> B_inst1 = B()
>>> B_inst2 = B()
>>> B_inst1.b
[1, 1]
>>> B_inst2.b
[1, 1]

Правильно ли я понял, что здесь при инициализации каждого объекта, фактически, происходит что-то такое: self.b = cls.b?
То есть в аттрибут экземпляра класса копируется ссылка на соответствующий аттрибут класса?

Тогда почему после выполнения такого кода все объекты имеют b разного значения:

>>> class B(object):
	b = []
	def __init__(self):
		self.b = []
		self.b.append(1)
		
>>> B_inst1 = B()
>>> B_inst1.b
[1]
>>> B.b
[]
>>> B_inst1.b = [1,2,3]
>>> B_inst2 = B()
>>> B_inst1.b
[1, 2, 3]
>>> B_inst2.b
[1]
>>> B.b
[]

Ведь если бы все объекты ссылались на один и тот же список класса, то у всех были бы одинаковые значения. Или если мы в инициализации ЯВНО указываем определение параметров, то ВНЕЗАПНО экземпляру выдается свой собственный список с уникальной ссылкой?

Правильно ли я понял вас?

Офлайн

#9 Июнь 26, 2012 13:52:24

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Вопрос про классы.

vault
Тогда почему после выполнения такого кода все объекты имеют b разного значения:
Происходит затенение атрибутов класса атрибутами экземпляра:
self.b = []
Теперь экземпляр содержит свой список. Старый список доуступен по B.b.
Было похожее обсуждение http://python.su/forum/post/87655/
и основная ссылка оттуда http://stackoverflow.com/a/69067/1052325

Офлайн

#10 Июнь 26, 2012 14:06:18

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Вопрос про классы.

vault
Правильно ли я понял, что здесь при инициализации каждого объекта, фактически, происходит что-то такое: self.b = cls.b?
Ой-ой-ой.
Никакой cls не определен в твоем классе.
self, cls, instance - это не ключевые слова, это общепринятые имена для параметра в методах.



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version