sobrecargar - tutorial poo python
Clases finales en Python 3.x- algo que Guido no me está diciendo? (4)
Esta pregunta se basa en muchas suposiciones. Si una suposición es incorrecta, entonces todo se cae. Todavía soy relativamente nuevo en Python y acabo de ingresar a la fase curiosa / exploratoria.
Tengo entendido que Python no admite la creación de clases que no se pueden subclasificar (clases finales ). Sin embargo, me parece que la clase bool en Python no se puede subclasificar. Esto tiene sentido cuando se considera la intención de la clase bool (porque se supone que bool solo tiene dos valores: verdadero y falso), y estoy contento con eso. Lo que quiero saber es cómo se marcó esta clase como final.
Entonces mi pregunta es: ¿cómo exactamente Guido logró evitar la subclasificación de 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
Pregunta relacionada: ¿Por qué no puedo extender bool en Python?
¡Tenemos una pequeña biblioteca para hacer eso! 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`
...
caracteristicas:
- Sin conflictos de metaclases
- Sin sobrecarga de tiempo de ejecución
- Sin dependencias
- Indicaciones de tipo incluidas
- Diseñado para ser lo más simple posible
En Python 3.6, puede bloquear la creación de subclases sin utilizar una metaclase como esta:
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
Puede simular el mismo efecto de Python 3.x con bastante facilidad:
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
dará la siguiente salida:
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
Usted podría hacer esto solo a través de la API C. Borre el bit Py_TPFLAGS_BASETYPE
de los tp_flags
del objeto tipo.
De esta manera: http://svn.python.org/projects/python/trunk/Objects/boolobject.c (vs intobject.c donde se establece Py_TPFLAGS_BASETYPE
).