__slot__
屬性被分配在該對象的本機存儲器的表示,和相關聯的訪問然後實際的類描述符使用本地C方法CPython的設置和檢索歸因於每個時隙中的Python對象的參考屬性上類實例作爲C結構。
描述符的插槽,在Python名爲member_descriptor
呈現在這裏定義:https://github.com/python/cpython/blob/master/Objects/descrobject.c
您不能執行或以任何方式提高從純Python代碼,這些描述符不使用ctypes的與本地代碼進行交互。
有可能通過做類似
class A:
__slots__ = "a"
member_descriptor = type(A.a)
去他們的類型,那麼可以supose將有可能繼承它,並寫出推導__get__
和__set__
方法,可以做到chekings和這樣的 - 但不幸的是,它不能作爲基類。
但是,可以編寫其他並行描述符,這些描述符可以調用本地描述符來實際更改代碼。 通過使用元類,可以在創建類時重命名傳入的__slots__
並將它們的訪問包裝在可執行額外檢查的自定義描述符中 - 甚至可以從「dir」中隱藏。
所以,對一個天真的類型檢查插槽變種元類,一個人可能
class TypedSlot:
def __init__(self, name, type_):
self.name = name
self.type = type_
def __get__(self, instance, owner):
if not instance:
return self
return getattr(instance, "_" + self.name)
def __set__(self, instance, value):
if not isinstance(value, self.type):
raise TypeError
setattr(instance, "_" + self.name, value)
class M(type):
def __new__(metacls, name, bases, namespace):
new_slots = []
for key, type_ in namespace.get("__slots__", {}).items():
namespace[key] = TypedSlot(key, type_)
new_slots.append("_" + key)
namespace["__slots__"] = new_slots
return super().__new__(metacls, name, bases, namespace)
def __dir__(cls):
return [name for name in super().__dir__() if name not in cls.__slots__]