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

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

off999 2024-11-17 14:33 84 浏览 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))

相关推荐

阿里云国际站ECS:阿里云ECS如何提高网站的访问速度?

TG:@yunlaoda360引言:速度即体验,速度即业务在当今数字化的世界中,网站的访问速度已成为决定用户体验、用户留存乃至业务转化率的关键因素。页面加载每延迟一秒,都可能导致用户流失和收入损失。对...

高流量大并发Linux TCP性能调优_linux 高并发网络编程

其实主要是手里面的跑openvpn服务器。因为并没有明文禁p2p(哎……想想那么多流量好像不跑点p2p也跑不完),所以造成有的时候如果有比较多人跑BT的话,会造成VPN速度急剧下降。本文所面对的情况为...

性能测试100集(12)性能指标资源使用率

在性能测试中,资源使用率是评估系统硬件效率的关键指标,主要包括以下四类:#性能测试##性能压测策略##软件测试#1.CPU使用率定义:CPU处理任务的时间占比,计算公式为1-空闲时间/总...

Linux 服务器常见的性能调优_linux高性能服务端编程

一、Linux服务器性能调优第一步——先搞懂“看什么”很多人刚接触Linux性能调优时,总想着直接改配置,其实第一步该是“看清楚问题”。就像医生看病要先听诊,调优前得先知道服务器“哪里...

Nginx性能优化实战:手把手教你提升10倍性能!

关注△mikechen△,十余年BAT架构经验倾囊相授!Nginx是大型架构而核心,下面我重点详解Nginx性能@mikechen文章来源:mikechen.cc1.worker_processe...

高并发场景下,Spring Cloud Gateway如何抗住百万QPS?

关注△mikechen△,十余年BAT架构经验倾囊相授!大家好,我是mikechen。高并发场景下网关作为流量的入口非常重要,下面我重点详解SpringCloudGateway如何抗住百万性能@m...

Kubernetes 高并发处理实战(可落地案例 + 源码)

目标场景:对外提供HTTPAPI的微服务在短时间内收到大量请求(例如每秒数千至数万RPS),要求系统可弹性扩容、限流降级、缓存减压、稳定运行并能自动恢复。总体思路(多层防护):边缘层:云LB...

高并发场景下,Nginx如何扛住千万级请求?

Nginx是大型架构的必备中间件,下面我重点详解Nginx如何实现高并发@mikechen文章来源:mikechen.cc事件驱动模型Nginx采用事件驱动模型,这是Nginx高并发性能的基石。传统...

Spring Boot+Vue全栈开发实战,中文版高清PDF资源

SpringBoot+Vue全栈开发实战,中文高清PDF资源,需要的可以私我:)SpringBoot致力于简化开发配置并为企业级开发提供一系列非业务性功能,而Vue则采用数据驱动视图的方式将程序...

Docker-基础操作_docker基础实战教程二

一、镜像1、从仓库获取镜像搜索镜像:dockersearchimage_name搜索结果过滤:是否官方:dockersearch--filter="is-offical=true...

你有空吗?跟我一起搭个服务器好不好?

来人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。昨天闲的没事的时候,随手翻了翻写过的文章,发现一个很严重的问题。就是大多数时间我都在滔滔不绝的讲理论,却很少有涉及动手...

部署你自己的 SaaS_saas如何部署

部署你自己的VPNOpenVPN——功能齐全的开源VPN解决方案。(DigitalOcean教程)dockovpn.io—无状态OpenVPNdockerized服务器,不需要持久存储。...

Docker Compose_dockercompose安装

DockerCompose概述DockerCompose是一个用来定义和管理多容器应用的工具,通过一个docker-compose.yml文件,用YAML格式描述服务、网络、卷等内容,...

京东T7架构师推出的电子版SpringBoot,从构建小系统到架构大系统

前言:Java的各种开发框架发展了很多年,影响了一代又一代的程序员,现在无论是程序员,还是架构师,使用这些开发框架都面临着两方面的挑战。一方面是要快速开发出系统,这就要求使用的开发框架尽量简单,无论...

Kubernetes (k8s) 入门学习指南_k8s kubeproxy

Kubernetes(k8s)入门学习指南一、什么是Kubernetes?为什么需要它?Kubernetes(k8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用程序。它...

取消回复欢迎 发表评论: