python中双下划綫属性和方法详解

本文详细解析Python中__slots__与__dict__的使用与区别,包括节省内存、提高性能的方法,以及如何在类中同时使用两者。通过实例展示了__slots__在属性存储上的优势,以及其对继承的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

属性

__dict__

__slots__参考
用于更快地得到属性
更加节约内存

例1
_ slots _dict _的接收属性的不同。

class lqq():
    __slots__ = ('a',) # 元素为属性名;当设置了这个属性而且lqq没有继承没有__slot__属性的类(如object),则lqq没有默认的__dict__

class lqq1():#默认有__dict__
    pass

lq = lqq()
lq1 = lqq1()
lq.a = 1
lq1.b = 2 # 有__dict__属性,b:2,会以键值对的形式加入dict里
lq.b = 2 # 报错,因为slot里没有b,而且lq没有__dict__.可以自己print(lq.__dict__)会报错

例2
slots和dict并存

class lqq():
    __slots__ = ('a','__dict__') # 方法一:在slots里设置dict参数

class lqq2:#默认有dict
    pass

class lqq1(lqq2):方法二:继承dict
    __slots__ = ('a',)

lq = lqq()
lq1 = lqq1()

lq.b = 2 #不报错
lq1.b =2#不报错

例3
slots的继承

class lqq():
    __slots__ = ('a',) # 元素为属性名;当设置了这个属性而且lqq没有继承没有__slot__属性的类(如object),则lqq没有默认的__dict__

class lqq1(lqq):
    __slots__ = ('b',)

lq1 = lqq1()
lq1.a =2 # 不报错,继承了lqq的slots中的a

slots不能继承多个有非空slots的父类

class BaseA(object):
    __slots__ = ('a',)

class BaseB(object):
    __slots__ = ('b',)

class Child(BaseA, BaseB): __slots__ = ()

例4
更快

import timeit

class Foo(object): __slots__ = 'foo',

class Bar(object): pass

slotted = Foo()
not_slotted = Bar()

def get_set_delete_fn(obj):
    def get_set_delete():
        obj.foo = 'foo'
        obj.foo
        del obj.foo
    return get_set_delete
 
print(min(timeit.repeat(get_set_delete_fn(slotted))))
print(min(timeit.repeat(get_set_delete_fn(not_slotted))))

例5
更少内存,并存时,有限slots
dict储存会以键值对的形式储存

class lqq():
    __slots__ = ('a',)

lq = lqq()
lq.a = 1 #

class lqq1():
    pass

lq1 = lqq1()
lq1.a = 1 #
from sys import getsizeof

print(getsizeof(lq)) #48
print(getsizeof(lq1)) #56



class lqq():
    __slots__ = ('a','__dict__') # 元素为属性名;当设置了这个属性而且lqq没有继承没有__slot__属性的类(如object),则lqq没有默认的__dict__

lq = lqq()

lq.b = 2 #
lq.a = 1 #
print(lq.__dict__)#没有a
print(lq.__slots__)

方法

用法广的

1,__bool__
python定义的每一个对象都是可以判断真假的,而在需要判断的时候,会调用对象的__bool__方法(默认只能返回True或False)

class lqq():
    def __bool__(self):###类对象是真假
        return False
print(bool(lqqq1)) # False

2,***__repr__***
当你print一个对象的时候,打印出的信息其实就是repr(我统一不加下划线了)方法的返回的str。在namedtuple中简化了以下:

class lqq(tuple):
    def __new__(_cls, x, y, ):
        'Create new instance of {typename}({a})'
        return tuple.__new__(_cls, (x, y,))

    def __repr__(self):
        'Return a nicely formatted representation string'
        print('repr')
        return self.__class__.__name__ + '(x='+str(1)+','+'y='+str(2)+')'

print(lqq(1, 2))
# 当没有重写repr的时候默认使用父类tuple的repr,结果(1, 2)
#使用后打印结果lqq(x=1,y=2)

有针对性的

介绍如在Collections Abstract Base Classes中的那些抽象函数。

__getitem__
序列(sequnce)和映射(maping)的抽象函数
方法返回值 对应 obj[aruge]

class lqq():

    def __getitem__(self, item):
        return 2

lqqq1 = lqq()

print(lqqq1[1])# __getitem__

__contains__

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值