Заключительные занятия по Python 3.x - что-то, что Гвидо не говорит мне? - PullRequest
31 голосов
/ 13 мая 2010

Этот вопрос основан на многих предположениях. Если одно предположение неверно, тогда все рушится. Я все еще относительно новичок в Python и только что вошел в любопытную / исследовательскую фазу.

Насколько я понимаю, Python не поддерживает создание классов, которые нельзя разделить на подклассы ( final classes). Однако мне кажется, что класс bool в Python нельзя разделить на подклассы. Это имеет смысл, когда рассматривается намерение класса bool (потому что bool должен иметь только два значения: true и false), и я доволен этим. То, что я хочу знать, это как этот класс был помечен как окончательный.

Итак, мой вопрос: как именно Гвидо удалось предотвратить создание подкласса bool?

>>> class TestClass(bool):
        pass

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    class TestClass(bool):
TypeError: type 'bool' is not an acceptable base type

Смежный вопрос: Почему я не могу расширить bool в Python?

Ответы [ 4 ]

45 голосов
/ 13 мая 2010

Вы можете смоделировать тот же эффект из Python 3.x довольно просто:

class Final(type):
    def __new__(cls, name, bases, classdict):
        for b in bases:
            if isinstance(b, Final):
                raise TypeError("type '{0}' is not an acceptable base type".format(b.__name__))
        return type.__new__(cls, name, bases, dict(classdict))

class C(metaclass=Final): pass

class D(C): pass

даст следующий вывод:

Traceback (most recent call last):
  File "C:\Temp\final.py", line 10, in <module>
    class D(C): pass
  File "C:\Temp\final.py", line 5, in __new__
    raise TypeError("type '{0}' is not an acceptable base type".format(b.__name__))
TypeError: type 'C' is not an acceptable base type
13 голосов
/ 13 мая 2010

Вы можете сделать это только через C API. Очистите Py_TPFLAGS_BASETYPE бит tp_flags объекта типа.

Вот так: http://svn.python.org/projects/python/trunk/Objects/boolobject.c (против intobject.c , где установлено Py_TPFLAGS_BASETYPE).

2 голосов
/ 14 июля 2018

Final и @final типы теперь доступны в typing_extensions.

Я написал статью, охватывающую почти каждую часть этого нового типа: https://sobolevn.me/2018/07/real-python-contants

Некоторые примеры с классами:

from typing_extensions import final

@final
class HRBusinessUnit(AbstractBusinessUnit):
    def grant_permissions(self) -> None:
        self.api.do_some_hr_stuff()


class SubHRBusinessUnit(HRBusinessUnit):  # mypy will raise an error
    def grant_permissions(self) -> None:
        self.api.do_some_it_stuff()

И с константами:

from typing_extensions import Final

DAYS_IN_A_WEEK: Final = 7
DAYS_IN_A_WEEK = 8  # mypy will raise an error

Также у нас есть небольшая библиотека для записи final классов, которые также проверяются во время выполнения! https://github.com/wemake-services/final-class

from final_class import final


@final
class Example(object):  # You won't be able to subclass it!
    ...


class Error(Example):  # Raises `TypeError`
    ...

Особенности:

  • Нет конфликтов метаклассов
  • Нет времени выполнения
  • Нет зависимостей
  • Тип подсказки включены
  • Разработан так, чтобы быть максимально простым
1 голос
/ 14 июля 2018

В Python 3.6 вы можете заблокировать подклассы без использования метакласса, подобного этому:

class SomeBase:

    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        if cls is not SomeBase:
            raise TypeError("SomeBase does not support polymorphism.  Use composition over inheritance.")


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