Можно ли расширять как старые, так и новые классы стилей? - PullRequest
5 голосов
/ 29 октября 2009

Когда я расширил некоторые сгенерированные инструментом классы, я не осознавал, что это классы старого стиля, пока не попытался использовать super (). Super () не работает со старыми классами, поэтому я получил эту ошибку:

TypeError: super() argument 1 must be type, not classobj

Например, попробуйте этот фрагмент:

>>> class A:
...     def greet(self):
...         print "A says hi"
...
>>> class B(A):
...     def greet(self):
...         print "B says hi"
...
>>> super(B, B()).greet()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: super() argument 1 must be type, not classobj

Мне было просто любопытно, что произойдет, если я также расширю B из объекта, чтобы сделать его новым стилевым классом, и, похоже, что super () работает.

>>> class B(A, object):
...     def greet(self):
...         print "B says hi"
...
>>> super(B, B()).greet()
A says hi

Это подходящий обходной путь или у меня будут некоторые нежелательные последствия позже?

Ответы [ 3 ]

4 голосов
/ 29 октября 2009

Классы нового стиля были рекомендованы в Python, так как они были введены в Python 2.2. В Python 3.x доступны только классы нового стиля. Поэтому я рекомендую вам переключиться на новый класс.

Мне не известно о каких-либо реальных проблемах, которые могут у вас возникнуть при этом. По большей части классы нового стиля просто приносят новые функции, такие как super(), реально работающие. Если у вас есть код, который сложным образом полагается на семантику классов старого стиля, этот код, конечно, сломается. (Единственный пример, который приходит на ум - это знаменитая картина Борга от известного Алекса Мартелли.)

Здесь - ссылка на справочное руководство по Python для обсуждения новых классов стилей по сравнению с классами старого стиля («классические»). И здесь - это ссылка на классическое эссе, где Гвидо ван Россум объясняет, почему были введены классы нового стиля.

Я использую только классы нового стиля в своем коде, и я призываю вас сделать то же самое.

1 голос
/ 30 октября 2009

Если вы не можете изменить генератор, чтобы он генерировал классы нового стиля, вы могли бы постобработать файл, чтобы сделать их новым стилем:

import re
pat = re.compile("^(.*class\s+\w+)(:.*)$")
out_file = open("edited_file.py", "w")
for line in open("generated_file.py"):
    m = pat.match(line)
    if m:
        line = m.group(1) + "(object)" + m.group(2) + "\n"
    out_file.write(line)

out_file.close()

Если вы не хотите этого делать по какой-то причине, тогда, конечно, продолжайте и сделайте подкласс как исходного класса, так и object. Насколько я знаю, это должно работать просто отлично; Ваш новый класс будет классом нового стиля.

В книге Python в двух словах (Алекс Мартелли, опубликованной O'Reilly) говорится, что если вы объявляете класс с базовыми классами, и хотя бы один из базовых классов является новым стилем, всегда будет классом нового стиля. В нем не перечислены какие-либо особые предупреждения или опасности, связанные с этим действием. Я думаю, ты в порядке.

0 голосов
/ 29 октября 2009

Я не вижу проблем в смешении классических и новых стилей, если только некоторые методы не используют классическую семантику или ваша классическая база не использует метакласс (метакласс потомства всегда будет классом нового стиля).

С другой стороны, я больше не вижу смысла использовать классические классы, поэтому предпочтительным является изменение class A: на class A(object):.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...