Найти - Пользователи
Полная версия: Вопрос про классы.
Начало » Python для новичков » Вопрос про классы.
1 2 3
vault
Продолжил решение этих задач:
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>

Не могу придумать аккуратного решения без использования, например, какого-нибудь общего списка. Предполагаю, что тут есть какие-то тонкости, которые я не учел. Кто как решит задачку?
fata1ex
А что не так со списком self._instances?
vault
fata1ex
А что не так со списком self._instances?
А можно поподробнее? Если не сложно, можете набросать первую часть задания - без механизма итератора?
fata1ex
Не 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 тоже могут пригодиться, раз уж вы так последовательно решили изучать питон :)
vault
Спасибо огромное! Приступил к чтению.
vault
Покопался с метаклассами, ужаснулся, впечатлился. Статьи отличные, спасибо.
Но возник вопрос: а зачем тут, в принципе, метаклассы? Собственно, ковыряя и переиначивая решение, достиг нужного результата проще:

class Reg(object):
	_instances = []
	def __init__(self):
		self._instances.append(self)
	def __iter__(self):
		return iter(_instances)
vault
Правда этот вопрос вызвал у меня сомнение великое:
Скажите, почему работает так:
>>>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 изменяется и хранится для класса, а переменная а - для объекта?

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

Извините, я, видимо, не очень понимаю суть неизменяемых типов. Мне казалось, что просто при передаче аргумента на изменяемые типы в функцию, или присваивания другой переменной, передается указатель на ту же самую структуру данных.
Но почему здесь-то a относится к self, а b к cls? Ведь в __init__ мы аппендим к селф, а не к цлс? Какой механизм действий при создании экземпляра класса?
FishHook
vault
dimy44
А что, собственно, вы ожидали? Обычное поведение списков. Создавая новый инстанс, вы вызываете __init__, каждый раз добавляя в свой список единицу. Нового списка-то вы там не создаете. Другое дело неизменяемые типы, инт, self.a += 1 это уже другая переменная.

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

This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB