You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建类似slice的、实例属性全只读的一等对象类?

如何创建类似内置slice的类?拆解内置slice的特殊行为

嘿,这个问题挖到了Python内置类型的底层细节,相当有意思!我来一步步帮你理清楚:

首先搞懂:内置slice为什么没有__dict__?

内置的slice是用C语言实现的扩展类型,不是纯Python类——这是它所有特殊行为的核心原因。

虽然它的元类确实是type,但C扩展类型可以绕过Python层面的很多默认规则:

  • 它的实例属性不是存储在__dict__里,而是直接存在C结构体的字段中,根本不需要__dict__来动态存储属性。
  • 属性的只读特性也是在C层面实现的:当你尝试修改slice实例的start/stop/step时,C代码会直接抛出AttributeError,完全不需要Python层面重写__setattr__。

而我们用纯Python写的类,默认会给每个实例分配__dict__,用来支持动态添加属性——除非你用__slots__显式禁用它。

用纯Python复刻类似slice的类

要实现一个“没有__dict__、属性只读”的类,我们可以结合__slots__和自定义__setattr__来模拟:

示例代码

class MySlice:
    # 用__slots__定义允许的属性,同时禁用__dict__
    __slots__ = ('start', 'stop', 'step')

    def __init__(self, start=None, stop=None, step=None):
        # 初始化时直接调用object的__setattr__,绕过自定义的限制
        object.__setattr__(self, 'start', start)
        object.__setattr__(self, 'stop', stop)
        object.__setattr__(self, 'step', step)

    def __setattr__(self, name, value):
        # 阻止任何后续的属性修改
        raise AttributeError(f"Cannot assign to attribute '{name}' of MySlice instance")

    def __repr__(self):
        return f"MySlice(start={self.start}, stop={self.stop}, step={self.step})"

测试验证

# 创建实例
s = MySlice(1, 10, 2)
print(s)  # 输出: MySlice(start=1, stop=10, step=2)

# 验证没有__dict__
print(hasattr(s, '__dict__'))  # 输出: False

# 尝试修改属性会报错
try:
    s.start = 5
except AttributeError as e:
    print(e)  # 输出: Cannot assign to attribute 'start' of MySlice instance

补充说明

  • 如果你不需要完全禁用所有属性修改,也可以用property给每个属性设置只读的setter:

    class MySlice:
        __slots__ = ('_start', '_stop', '_step')
    
        def __init__(self, start=None, stop=None, step=None):
            self._start = start
            self._stop = stop
            self._step = step
    
        @property
        def start(self):
            return self._start
    
        @property
        def stop(self):
            return self._stop
    
        @property
        def step(self):
            return self._step
    

    这种方式更灵活,但本质还是依赖__slots__移除__dict__。

  • 内置slice没有用__slots__,因为它根本不需要Python层面的属性存储机制——C实现直接跳过了这些环节。

内容的提问来源于stack exchange,提问作者Charif DZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:19:05