python-3 内置方法

本文深入探讨了Python中特殊方法的应用,包括__getattr__、__setattr__、__delattr__等属性管理方法,以及__getattribute__的方法作用。此外,还介绍了描述符协议(__get__、__set__、__delete__)和容器协议(__getitem__、__setitem__、__delitem__),并解释了__str__、__repr__和__format__如何影响对象的字符串表示。

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

一、 _setattr_,_delattr_,_getattr_

 class Foo:
    x = 1

    def __init__(self, y):
        self.y = y

    def __getattr__(self, item):
        print('----> from getattr:你找的属性不存在')

    def __setattr__(self, key, value):
        print('----> from setattr')
        # self.key=value #这就无限递归了,你好好想想
        # self.__dict__[key]=value #应该使用它

    def __delattr__(self, item):
        print('----> from delattr')
        # del self.item #无限递归了
        self.__dict__.pop(item)


# __setattr__添加/修改属性会触发它的执行
f1 = Foo(10)
print(f1.__dict__)  # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值

print('==============')
f1.z = 3
print(f1.__dict__)

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

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

结果:
----> from setattr
{}
==============
----> from setattr
{}
==============
----> from delattr
{}
==============
----> from getattr:你找的属性不存在

二、_getattribute_

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

    def __getattr__(self, item):
        print('执行的是我')
        # return self.__dict__[item]


f1 = Foo(10)
print(f1.x)
print('============')
f1.xxxxxx  # 不存在的属性访问,触发__getattr__

结果:
10
============
执行的是我
class Foo:
    def __init__(self, x):
        self.x = x

    def __getattribute__(self, item):
        print('不管是否存在,我都会执行')


f1 = Foo(10)
f1.x
print('===================')
f1.xxxxxx

结果:
不管是否存在,我都会执行
===================
不管是否存在,我都会执行
class Foo:
    def __init__(self, x):
        self.x = x

    def __getattr__(self, item):
        print('执行的是我')
        # return self.__dict__[item]

    def __getattribute__(self, item):
        print('不管是否存在,我都会执行')
        # raise AttributeError('哈哈')


f1 = Foo(10)
f1.x
print('==================')
f1.xxxxxx

结果:
不管是否存在,我都会执行
==================
不管是否存在,我都会执行
class Foo:
    def __init__(self, x):
        self.x = x

    def __getattr__(self, item):
        print('执行的是我')
        # return self.__dict__[item]

    def __getattribute__(self, item):
        print('不管是否存在,我都会执行')
        raise AttributeError('哈哈')


f1 = Foo(10)
f1.x
print('==================')
f1.xxxxxx

结果:
不管是否存在,我都会执行
执行的是我
==================
不管是否存在,我都会执行
执行的是我

当__getattribute__与__getattr__同时存在,只会执行__getattribute__
如果__getattribute__在执行过程中抛出异常AttributeError,两个都会执行,不管属性存不存在。

三、_get_、_set_、_delete_

_get_():调用一个属性时,触发
_set_():为一个属性赋值时,触发
_delete_():采用del删除属性时,触发

# 描述符Str
class Str:
    def __get__(self, instance, owner):
        print('Str调用')

    def __set__(self, instance, value):
        print('Str设置...')

    def __delete__(self, instance):
        print('Str删除...')


# 描述符Int
class Int:
    def __get__(self, instance, owner):
        print('Int调用')

    def __set__(self, instance, value):
        print('Int设置...')

    def __delete__(self, instance):
        print('Int删除...')


class People:
    name = Str()
    age = Int()

    def __init__(self, name, age):  # name被Str类代理,age被Int类代理,
        self.name = name
        self.age = age


# 何地?:定义成另外一个类的类属性

# 何时?:且看下列演示

p1 = People('winnie', 18)

print('==================')
# 描述符Str的使用
p1.name = 'allen'
del p1.name

print('==================')
# 描述符Int的使用
p1.age = 18
del p1.age

print('==================')
# 我们来瞅瞅到底发生了什么
print(p1.__dict__)
print(People.__dict__)

print('==================')
# 补充
print(type(p1) == People)  # type(obj)其实是查看obj是由哪个类实例化来的
print(type(p1).__dict__ == People.__dict__)

结果:
Str设置...
Int设置...
==================
Str设置...
Str删除...
==================
Int设置...
Int删除...
==================
{}
{'__module__': '__main__', 'name': <__main__.Str object at 0x052131F0>, 'age': <__main__.Int object at 0x05213250>, '__init__': <function People.__init__ at 0x052053D8>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
==================
True
True

四、_setitem_、_getitem_、_delitem_

class Foo:  # Dict
    def __init__(self, name):
        self.name = name

    def __getitem__(self, item):  # item='namexxx'
        print('getitem...')
        return self.__dict__.get(item)

    def __setitem__(self, key, value):
        print('setitem...')
        # print(key,value)
        self.__dict__[key] = value

    def __delitem__(self, key):
        print('delitem...')
        # print(key)
        del self.__dict__[key]


obj = Foo('winnie')
print(obj.__dict__)

print('==============================')
# 查看属性:obj.属性名
print(obj['namexxx'])  # obj.name

print('==============================')
# 设置属性:
# obj.sex = 'male' # 不会走setitem...
obj['sex'] = 'male'

print(obj.__dict__)
print(obj.sex)

print('==============================')
# 删除属性
# del obj.name #不会触发delitem...
del obj['name']

print(obj.__dict__)

结果:
{'name': 'winnie'}
==============================
getitem...
None
==============================
setitem...
{'name': 'winnie', 'sex': 'male'}
male
==============================
delitem...
{'sex': 'male'}

五、_str_、repr、_format_

  • str函数或者print函数调用的是obj.str()

  • repr函数或者交互式解释器调用的是obj.repr()

    注意:

  • 如果__str__没有被定义,那么就会使用__repr__来代替输出。

  • __str__和__repr__方法的返回值都必须是字符串。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值