百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

python中self有哪些赋值方式(python中self的用法)

off999 2024-11-17 14:33 22 浏览 0 评论

这周比较忙,趁周末有空更新一篇文章,本文主要讲解类中实例赋值涉及的几种场景。

方法一;赋值即定义
场景:常用方式
样例:self.name = laokoo

方法二;setattr函数赋值
场景:使用字符串的方式操作实例的属性
样例: setattr(self,'name','laokoo')

方法三;实例字典赋值
场景:非标方式,本质上实例就是通过这种方式储存属性的
样例:self.__dict__[name] = 'laokoo'

方法四;类中实现__setattr__魔术方法
场景:=号赋值的方式,setattr函数的赋值本质上都是调用__setattr__魔术方法进行赋值。
    __setattr__魔术方法中调用基类的该方法可以实现self属性的赋值
    __setattr__魔术方法中使用实例字典赋值的方式可以实现self属性赋值
    __setattr__魔术方法中如果使用=号赋值或者setattr函数会引起无限递归
样例:详见下方代码

方法五;类属性是另外一个类的实例,该类属性也是实例的属性
场景:实例访问类属性会触发描述器调用装饰类__get__方法的返回值
    实例通过=号赋值会触发描述器调用装饰类的__set__方法进行属性设置
样例:详见下方代码

方法六,类中实现__slots__属性
场景:类中实现该方法后会禁用掉实例的字典,实例的属性全部通过类属性进行储存。
    该属性主要针对实例属性过多,内存资源不足,实例属性较为简单的场景
    __slots__不支持动态添加属性,__slots__不支持类继承
建议:可以使用tracemalloc模块测试元组和字典内存空间占用效果
样例:详见下方代码

备注:方法六中我打印了实例属性"member 'name' of 'Person' objects"
    类型是"class 'member_descriptor'"。小弟其实不太明白__slots__
    后端的实现原理,例如__slots__是用什么数据类型存放数据,member_descriptor
    类中不同实例同一个属性是如何存储的。

惯例先上汇总说明,后上代码参考。为了方便大家测试,我将测试区代码封装成了多个小块,大家在测试时根据场景不同区分调用即可。

此外本次测试中描述器方法,反射方法,slots方法可能会相互干扰,所以大家如果有测试需求请测试时关闭掉存在干扰的选项(存在干扰的我已经在文中进行了说明),另外大家如果不太明白描述器原理也可以查看我之前整理的一篇关于描述器的说明。

class Face:

    def __get__(self, instance, owner):
        print('in get ~~~')
        return self

    # 装饰类必须实现set魔术方法才能影响功能类的赋值语句
    def __set__(self, instance, value):
        print('in set ~~~~')
        self.data = value

    def __repr__(self):
        return '<face instance>'


class Person:
    face = Face()

    # #最后测试再开启,slots会禁用掉实例的字典,所以代码中只要使用到实例__dict__的部分都会报错。测试该功能前请关闭dict使用项
    # __slots__ = ['name','age']

    def __init__(self, name):
        print('in init ~~~~')
        self.name = name
        # 观察face的值,观察实例的字典
        self.face = 'myface'

    # 第一阶段我们不设置该魔术方法,第二阶段开启该魔术方法
    def __setattr__(self, key, value):
        print('{} {} in setattr ~~~'.format(key, value))
        print(self.__dict__)
        # 测试一,调用基类方法观察效果
        super().__setattr__(key, value)
        # 测试二,直接使用实例字典赋值观察效果
        # self.__dict__[key] = value
        # 测试三,直接使用实例赋值观察效果
        # self.key = value
        # 测试四,使用setattr函数赋值观察效果
        # setattr(self,key,value)
        print(self.__dict__)


def test_show(user_input: int):
    """为了方便观察,我将一个测试场景进行了打印区分"""
    if user_input == 1:
        """第一阶段使用方式一进行测试
        测试方法:通过=的方式直接赋值
        观察结果:name的值,实例的字典"""
        laokoo = Person('laokoo')
        print(laokoo.name)
        laokoo.name = 'kabu'
        print(laokoo.__dict__)
        print(laokoo.name)
    elif user_input == 2:
        """第一阶段使用方式二进行测试
        测试方法:setattr()函数赋值
        观察结果:name的值,实例的字典"""
        laokoo = Person('laokoo')
        print(laokoo.name)
        setattr(laokoo, 'name', 'kabu')
        print(laokoo.__dict__)
        print(laokoo.name)
    elif user_input == 3:
        """第一阶段使用第三种方式测试
        测试方法:使用实例字典直接赋值(非标)
        观察结果:name的值,实例字典"""
        laokoo = Person('laokoo')
        print(laokoo.name)
        laokoo.__dict__['name'] = 'kabu'
        print(laokoo.__dict__)
        print(laokoo.name)
    elif user_input == 4:
        """第二阶段使用第四种方式测试,这里的知识点比较多
        测试方式:直接赋值,setattr函数赋值,这两种方法在__setattr__中测试
        观察结果:name的值,__setattr__方法执行,实例字典"""
        laokoo = Person('laokoo')
        """观察实例的初始化逻辑,先调用init,然后遇见赋值语句,直接调用__setattr__魔术方法,然后将key,value传入
        因为我们的赋值动作最终实现效果是往实例的字典添加键值对,所以该魔术方法最终也会执行该操作"""
        print(laokoo.name)
    elif user_input == 5:
        """第三阶段使用第五种测试,这里会用到描述器,建议关闭掉功能类的setattr方法,不然显示内容太多
        测试方法:直接赋值,setattr函数赋值
        观察结果:face的值"""
        laokoo = Person('laokoo')
        print(laokoo.face)
        # 观察data是否由值输出
        print(laokoo.face.data)
    elif user_input == 6:
        """第四阶段使用第六种测试,这里会用到__slots__
        """
        laokoo = Person('laokoo')
        setattr(laokoo,'age',18)
        # setattr(laokoo,'x','xx')
        #实例字典会被禁用,会使用类字典储存属性值
        # print(laokoo.__dict__)
        #name字段对应的值是'name': <member 'name' of 'Person' objects>(类型<class 'member_descriptor'>),
        print(Person.__dict__)
        #开启__slot__后name才会切换到类属性
        # print(type(Person.name))

相关推荐

面试官:来,讲一下枚举类型在开发时中实际应用场景!

一.基本介绍枚举是JDK1.5新增的数据类型,使用枚举我们可以很好的描述一些特定的业务场景,比如一年中的春、夏、秋、冬,还有每周的周一到周天,还有各种颜色,以及可以用它来描述一些状态信息,比如错...

一日一技:11个基本Python技巧和窍门

1.两个数字的交换.x,y=10,20print(x,y)x,y=y,xprint(x,y)输出:102020102.Python字符串取反a="Ge...

Python Enum 技巧,让代码更简洁、更安全、更易维护

如果你是一名Python开发人员,你很可能使用过enum.Enum来创建可读性和可维护性代码。今天发现一个强大的技巧,可以让Enum的境界更进一层,这个技巧不仅能提高可读性,还能以最小的代价增...

Python元组编程指导教程(python元组的概念)

1.元组基础概念1.1什么是元组元组(Tuple)是Python中一种不可变的序列类型,用于存储多个有序的元素。元组与列表(list)类似,但元组一旦创建就不能修改(不可变),这使得元组在某些场景...

你可能不知道的实用 Python 功能(python有哪些用)

1.超越文件处理的内容管理器大多数开发人员都熟悉使用with语句进行文件操作:withopen('file.txt','r')asfile:co...

Python 2至3.13新特性总结(python 3.10新特性)

以下是Python2到Python3.13的主要新特性总结,按版本分类整理:Python2到Python3的重大变化Python3是一个不向后兼容的版本,主要改进包括:pri...

Python中for循环访问索引值的方法

技术背景在Python编程中,我们经常需要在循环中访问元素的索引值。例如,在处理列表、元组等可迭代对象时,除了要获取元素本身,还需要知道元素的位置。Python提供了多种方式来实现这一需求,下面将详细...

Python enumerate核心应用解析:索引遍历的高效实践方案

喜欢的条友记得关注、点赞、转发、收藏,你们的支持就是我最大的动力源泉。根据GitHub代码分析统计,使用enumerate替代range(len())写法可减少38%的索引错误概率。本文通过12个生产...

Python入门到脱坑经典案例—列表去重

列表去重是Python编程中常见的操作,下面我将介绍多种实现列表去重的方法,从基础到进阶,帮助初学者全面掌握这一技能。方法一:使用集合(set)去重(最简单)pythondefremove_dupl...

Python枚举类工程实践:常量管理的标准化解决方案

本文通过7个生产案例,系统解析枚举类在工程实践中的应用,覆盖状态管理、配置选项、错误代码等场景,适用于Web服务开发、自动化测试及系统集成领域。一、基础概念与语法演进1.1传统常量与枚举类对比#传...

让Python枚举更强大!教你玩转Enum扩展

为什么你需要关注Enum?在日常开发中,你是否经常遇到这样的代码?ifstatus==1:print("开始处理")elifstatus==2:pri...

Python枚举(Enum)技巧,你值得了解

枚举(Enum)提供了更清晰、结构化的方式来定义常量。通过为枚举添加行为、自动分配值和存储额外数据,可以提升代码的可读性、可维护性,并与数据库结合使用时,使用字符串代替数字能简化调试和查询。Pytho...

78行Python代码帮你复现微信撤回消息!

来源:悟空智能科技本文约700字,建议阅读5分钟。本文基于python的微信开源库itchat,教你如何收集私聊撤回的信息。[导读]Python曾经对我说:"时日不多,赶紧用Python"。于是看...

登录人人都是产品经理即可获得以下权益

文章介绍如何利用Cursor自动开发Playwright网页自动化脚本,实现从选题、写文、生图的全流程自动化,并将其打包成API供工作流调用,提高工作效率。虽然我前面文章介绍了很多AI工作流,但它们...

Python常用小知识-第二弹(python常用方法总结)

一、Python中使用JsonPath提取字典中的值JsonPath是解析Json字符串用的,如果有一个多层嵌套的复杂字典,想要根据key和下标来批量提取value,这是比较困难的,使用jsonpat...

取消回复欢迎 发表评论: