Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 24, 2012 15:55:41

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

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

Продолжил решение этих задач:
http://pyobject.ru/blog/2010/02/04/python-quiz/
И столкнулся с проблемами при решении 4-й из темы “классы”:

Написать класс, который регистрирует свои экземпляры и предоставляет интерфейс итератора по ним

>>> x = Reg()
>>> x
<Reg instance at 0x98b6ecc>
>>> y = Reg()
>>> y
<Reg instance at 0x98b6fec>
>>> z = Reg()
<Reg instance at 0x98ba02c>
>>> for i in Reg:
...     print i
<Reg instance at 0x98b6ecc>
<Reg instance at 0x98b6fec>
<Reg instance at 0x98ba02c>

Не могу придумать аккуратного решения без использования, например, какого-нибудь общего списка. Предполагаю, что тут есть какие-то тонкости, которые я не учел. Кто как решит задачку?

Офлайн

#2 Июнь 24, 2012 16:17:26

fata1ex
От:
Зарегистрирован: 2009-07-11
Сообщения: 732
Репутация: +  52  -
Профиль   Отправить e-mail  

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

А что не так со списком self._instances?



Офлайн

#3 Июнь 24, 2012 16:41:49

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

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

fata1ex
А что не так со списком self._instances?
А можно поподробнее? Если не сложно, можете набросать первую часть задания - без механизма итератора?

Офлайн

#4 Июнь 24, 2012 17:04:35

fata1ex
От:
Зарегистрирован: 2009-07-11
Сообщения: 732
Репутация: +  52  -
Профиль   Отправить e-mail  

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

Не self, a cls.

class MetaReg(type):
    def __iter__(cls):
        return iter(cls._instances)
 
 
class Reg(object):
    __metaclass__ = MetaReg
     
    _instances = []
    def __new__(cls, *args, **kwargs):
        instance = super(Reg, cls).__new__(cls, *args, **kwargs)
        cls._instances.append(instance)
 
        return instance
  
 
a, b, c = Reg(), Reg(), Reg()
for obj in Reg:
    print obj

Если не очень понятно, почитайте про метаклассы (они управляют поведением классов, что нам тут и нужно как раз для итерации по классу). Есть очень неплохой топик на SO, переведённый недавно на хабре.
Ну и мои любимые ссылки: 1, 2, 3, 4 тоже могут пригодиться, раз уж вы так последовательно решили изучать питон :)



Отредактировано fata1ex (Июнь 24, 2012 17:24:48)

Офлайн

#5 Июнь 24, 2012 17:34:45

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

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

Спасибо огромное! Приступил к чтению.

Офлайн

#6 Июнь 26, 2012 00:24:52

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

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

Покопался с метаклассами, ужаснулся, впечатлился. Статьи отличные, спасибо.
Но возник вопрос: а зачем тут, в принципе, метаклассы? Собственно, ковыряя и переиначивая решение, достиг нужного результата проще:

class Reg(object):
	_instances = []
	def __init__(self):
		self._instances.append(self)
	def __iter__(self):
		return iter(_instances)

Офлайн

#7 Июнь 26, 2012 00:36:53

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

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

Правда этот вопрос вызвал у меня сомнение великое:
Скажите, почему работает так:

>>>class A(object):
	   a = 0
	   def __init__(self):
		   self.a+=1
>>>class B(object):
	   b = []
	   def __init__(self):
		   self.b.append(1)
>>> a1 = A()
>>> a2 = A()
>>> a2.a
1
>>> b1 = B()
>>> b2 = B()
>>> b2.b
[1, 1]

То есть почему список b изменяется и хранится для класса, а переменная а - для объекта?

Офлайн

#8 Июнь 26, 2012 08:57:55

dimy44
От: Евпатория
Зарегистрирован: 2012-04-21
Сообщения: 463
Репутация: +  42  -
Профиль  

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

А что, собственно, вы ожидали? Обычное поведение списков. Создавая новый инстанс, вы вызываете __init__, каждый раз добавляя в свой список единицу. Нового списка-то вы там не создаете. Другое дело неизменяемые типы, инт, self.a += 1 это уже другая переменная.

Офлайн

#9 Июнь 26, 2012 11:30:40

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

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

dimy44
А что, собственно, вы ожидали? Обычное поведение списков. Создавая новый инстанс, вы вызываете __init__, каждый раз добавляя в свой список единицу. Нового списка-то вы там не создаете. Другое дело неизменяемые типы, инт, self.a += 1 это уже другая переменная.

Извините, я, видимо, не очень понимаю суть неизменяемых типов. Мне казалось, что просто при передаче аргумента на изменяемые типы в функцию, или присваивания другой переменной, передается указатель на ту же самую структуру данных.
Но почему здесь-то a относится к self, а b к cls? Ведь в __init__ мы аппендим к селф, а не к цлс? Какой механизм действий при создании экземпляра класса?

Офлайн

#10 Июнь 26, 2012 11:44:29

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

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

vault
dimy44
А что, собственно, вы ожидали? Обычное поведение списков. Создавая новый инстанс, вы вызываете __init__, каждый раз добавляя в свой список единицу. Нового списка-то вы там не создаете. Другое дело неизменяемые типы, инт, self.a += 1 это уже другая переменная.

Извините, я, видимо, не очень понимаю суть неизменяемых типов. Мне казалось, что просто при передаче аргумента на изменяемые типы в функцию, или присваивания другой переменной, передается указатель на ту же самую структуру данных.
Но почему здесь-то a относится к self, а b к cls? Ведь в __init__ мы аппендим к селф, а не к цлс? Какой механизм действий при создании экземпляра класса?
b в твоём коде - аттрибут класса. Чтобы он стал аттрибутом объекта его нужно определять внутри метода.



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version