python3-内置方法

__init__,__setattr__,__delattr__,__getattr__

class Foo:
    x=1
    def __init__(self,y):
        print('__init__在实例化对象时调用')
        self.y=y

    def __getattr__(self, item):
        print('__getattr__只有在使用点调用属性且属性不存在的时候才会触发')

    def __setattr__(self, key, value):
        print('__setattr__ 赋值操作(添加/修改属性)会触发它的执行')

    def __delattr__(self, item):
        print('__delattr__删除属性的时候会触发')
        self.__dict__.pop(item)

#__setattr__ 赋值操作(添加/修改属性)会触发它的执行
f1=Foo(10)
print(f1.__dict__)
 # 重写了__setattr__,凡是赋值操作都会触发它的运行
f1.z=3
print(f1.__dict__)

#__delattr__删除属性的时候会触发
f1.__dict__['a']=3
#直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)

#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx

__getattr__、__getattribute__

class Foo:
    def __init__(self,x):
        self.x=x
    def __getattr__(self, item):
        print('__getattr__只有在使用点调用属性且属性不存在的时候才会触发')

    def __getattribute__(self, item):
        print('单独存在时,不管是否存在,都会执行')
        raise AttributeError('__getattribute__异常')

f1=Foo(10)
f1.x
f1.y

#当__getattribute__与__getattr__同时存在,只会执行__getattrbute__
#除非__getattribute__在执行过程中抛出异常AttributeError

__get__,__set__,__delete__(描述符)

描述符:本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
__get__():调用一个属性时,触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时,触发

class Foo: 
    def __get__(self, instance, owner):
        pass
    def __set__(self, instance, value):
        pass
    def __delete__(self, instance):
        pass

__str__、__repr__、__format__、 __del__、 __call__

__str__ 对象打印时触发,用来自定义打印信息
__repr__对象用于交互式解释器,若str没有被定义,则使用repr来代替输出
前两个必须返回值为字符串,否则抛出异常

__format__自定制格式化字符串
__del__ 对象被删时触发,内部可以用来回收对象以外的资源,如系统资源
__call__ 对象被调用时触发,用来实现对象的调用
format_dict={
    'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
    'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
    'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class test:
    def __init__(self, name, age, filepath):
        self.name = name
        self.age = age
        self.f = open(filepath, 'rt', encoding='utf-8')

    def __str__(self):
        return '<name:%s,age:%s>' % (self.name, self.age)

    def __repr__(self):
        return '<name:%s,age:%s>' % (self.name, self.age)
    
    def __format__(self,format_spec):
        if not format_spec or format_spec not in format_dict:
            format_spec = 'nat'
        fmt = format_dict[format_spec]
        return fmt.format(obj = self)

    def __del__(self):
        print('is deleted')
        # 进行回收对象关联的资源
        self.f.close()

    def __call__(self, *args, **kwargs):
        print(self, args, kwargs)


obj = test('t1', 18, 'D:\python\old_boy2\object_oriented\settings.py')
obj(1,2,a=3,b=4)
print(obj)
del obj

 __slots__

'''
1.__slots__:一个类变量;变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
2.引子:
     使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)
3.使用__slots__原因:
     字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__。
     当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。
     实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典,这跟元组或列表很类似。
     在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。
     使用__slots__一个不好的地方就是我们不能再给实例添加新的属性了,只能使用在__slots__中定义的那些属性名。
4.注意事项:
     __slots__的很多特性都依赖于普通的基于字典的实现。
     另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。
     大多数情况下,你应该只在那些经常被使用到 的用作数据结构的类上定义__slots__。
     比如在程序中需要创建某个类的几百万个实例对象 。

关于__slots__的一个常见误区:
     是它可以作为一个封装工具来防止用户给实例增加新的属性。
     尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。
     更多的是用来作为一个内存优化工具。

'''
class Foo:
    __slots__='x'


f1=Foo()
f1.x=1
f1.y=2#报错
print(f1.__slots__) #f1不再有__dict__

class Bar:
    __slots__=['x','y']
    
n=Bar()
n.x,n.y=1,2
n.z=3#报错

__next__和__iter__实现迭代器协议

class Foo:
    def __init__(self,x):
        self.x=x

    def __iter__(self):
        return self

    def __next__(self):
        n=self.x
        self.x+=1
        return self.x

f=Foo(3)
for i in f:
    print(i)

 __doc__

__doc__查看对象的注释(‘’‘xxxx’‘’)信息

class Foo:
    '我是描述信息'
    pass

print(Foo.__doc__)

__module__和__class__

__module__ 表示当前操作的对象在那个模块

__class__     表示当前操作的对象的类是什么

__enter__和__exit__

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
        # return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')


with Open('a.txt') as f:
    print('=====>执行代码块')
    # print(f,f.name)

类的专有方法:

__init__: 构造函数,在生成对象时调用
__del__: 析构函数,释放对象时使用
__repr__: 打印,转换
__setitem__: 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__cmp__: 比较运算
__call__: 函数调用
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__div__: 除运算
__mod__: 求余运算
__pow__: 乘方

猜你喜欢

转载自blog.csdn.net/qq_33961117/article/details/82113033