2014-11-04 3 views
5

Помимо очевидного, я думал, что я хотел бы попробовать это, на всякий случай:Есть ли способ подкласса генератора в Python 3?

def somegen(input=None): 
    ... 
    yield 
    ... 

gentype = type(somegen()) 
class subgen(gentype): 
    def best_function_ever(): 
     ... 

Увы, ответ Пизон был весьма враждебно:

"TypeError: Type generator is not an acceptable base type" 

Как назло, это проблема для меня. Видишь, я думал, что может быть будет быть забавным базовым типом для игры, если бы я дал ему шанс. Представьте мое удивление! .. и смятение. Разве нет способа заставить всемогущего Python увидеть что-то в этом роде?

Это, безусловно, вопрос о внешнем виде, поэтому, пожалуйста, не просто скажите, что это невозможно, если вы не можете сразу придумать способ. Python (особенно Py3) очень гибкий.

Конечно, если у вас есть доказательства того, почему он не может (не «не должен») быть базовым типом (PY3), то я сделать хочет увидеть и понять, что.

+0

«Генератор» - это тип 'метода'. «Класс» может наследовать только от других «классов». Это было бы аналогично строительству автомобиля из вождения. Я могу понять разочарование, потому что я считаю, что python должен иметь возможность делать что угодно и все, но я понимаю, почему они не нашли времени для его реализации. –

+0

@FarmerJoe Я не уверен, что получаю аналогию, но «метод» по существу (может быть, даже на самом деле) является подтипом 'function'. Кроме того, все это тип, даже сам тип;) – Inversus

+0

@FarmerJoe Что я имею в виду, так это то, что под обложками все «класс», даже «генератор». Где-то глубоко внутри себя, несомненно, найдется некоторый C-эквивалент «генератора (функции) класса», и это тот класс, который я ищу для «подкласса» (то есть: я совершенно счастлив делать что-то другое, что позволяет мне подобную гибкость) , – Inversus

ответ

1

Вы не можете подклассифицировать генератор, который определен как функция, используя yield, но вы можете использовать его в другом генераторе.

Просто это просто один:

def alphagen(n=27): 
    if n<0 or n > 27: n = 27 
    for i in range(n): 
     yield chr(ord('A') + i) 

Вы получаете:

>>>> [ a for a in alphagen(10)] 
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'] 

Вы можете использовать его в:

def alphastartgen(n=27): 
    resul = "" 
    for i in alphagen(n): 
     resul += i 
     yield resul 

А теперь вы получите:

>>> [ a for a in alphastartgen(8) ] 
['A', 'AB', 'ABC', 'ABCD', 'ABCDE', 'ABCDEF', 'ABCDEFG', 'ABCDEFGH'] 
+0

Это увлекательный угол. Я собираюсь поиграть с ним какое-то время. Я вернусь. Спасибо – Inversus

+0

Я вернулся от игры с этим немного, и я должен сказать: «О, да, это хороший материал». Рассмотрение определения внешнего генератора (функции), как определение класса, является именно таким сумасшедшим взломом, на который я надеялся. Большое спасибо. – Inversus

2

Соответствующий другой вопрос: Which classes cannot be subclassed?.

Это причина 2 в принятом ответе - подклассы типа должны быть реализованы на C, и он не был реализован для генераторов, вероятно, потому, что никто не видел прецедента.

Исходный код для объектов генератора - genobject.c, и вы можете увидеть на строке 349, что флаг Py_TPFLAGS_BASETYPE не установлен.

+1

Ooo. Это мило. Это единственное, что мешает моему подклассу ген? Есть ли другие части внутренних органов, которые нужно будет убедить? Может ли это быть сделано во время выполнения (monkeypatch?), Или я мог бы сделать собственную сборку? (длинная дорога, которую я пытаюсь избежать на данный момент lol) – Inversus

+0

Также .. как вы нашли этот флаг?Например, вы просто знали об этом, или вы следовали за кодом там или что-то еще? – Inversus

+0

I Googled и нашел предыдущий поток переполнения стека, к которому я привязался, и прочитал его ... И флага недостаточно, вам также нужно _implement_, как он будет работать (см., Скажем, код для списка) и перекомпилируйте Python. – RemcoGerlich