Python - 面向对象的属性,类方法,静态方法,实例方法的区别及用法详解

news2024/12/23 18:33:32

一. 前言

  • 在Python的面向对象编程中,类属性和实例属性是两个不同的概念,它们在作用域和使用方式上有所区别。
  • 在Python中的面向对象编程中有三种方法:实例方法、类方法和静态方法,它们之间的差异主要体现在参数传递和调用方式上。

二. 面向对象 - 类属性和实例属性

在 Python 中,类属性和实例属性的区别在于它们的作用域不同。

  • 类属性是属于类对象的属性,它的值对于类的所有实例来说是相同的,类属性可以通过类名或实例名访问
  • 实例属性是属于实例对象的属性,每个实例都可以有自己的属性值。实例属性只能通过实例名访问

1. 示例代码

class MyClass:
    class_attr = "I am a class attribute"

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


if __name__ == '__main__':
    obj1 = MyClass("I am an instance attribute of obj1")
    obj2 = MyClass("I am an instance attribute of obj2")

    print(obj1.class_attr)  # 输出 "I am a class attribute"
    print(obj2.class_attr)  # 输出 "I am a class attribute"

    print(obj1.ins_attr)  # 输出 "I am an instance attribute of obj1"
    print(obj2.ins_attr)  # 输出 "I am an instance attribute of obj2"

    obj1.class_attr = "I am a new update class attribute of obj1"
    print(obj1.class_attr)  # 输出 "I am a new update class attribute of obj1"
    print(obj2.class_attr)  # 输出 "I am a class attribute"

    MyClass.class_attr = "I am a new MyClass attribute"
    print(obj1.class_attr)  # 输出 "I am a new update class attribute of obj1"
    print(obj2.class_attr)  # 输出 "I am a new MyClass attribute"
    print(MyClass.class_attr)  # 输出 "I am a new MyClass attribute"

上面的代码中,我们定义了一个 MyClass 类,其中有一个类属性 class_attr 和一个实例属性 name。在实例化 obj1 和 obj2 之后,我们分别访问了它们的实例属性和类属性,然后我们修改了类属性的值,并且分别访问了两个实例的类属性值,最后打印了每个实例的属性值。

运行结果如下

在这里插入图片描述
从以上运行结果可以看到,

  • 当我们根据使用实例对象修改类属性时,该实例对象的类属性会改变,但只会作用于自身(修改的实例对象),不会影响其他实例的属性值。
  • 当我们通过直接修改类属性时,类属性会发生改变,并且生效作用于其他的实例对象,其他的实例对象访问结果会变成类修改类属性后的结果,而实例对象修改过后的类属性却没有受到影响,它的类属性的值是它(实例对象)修改过后的值。

总结一下,类属性是一个类的全局变量,所有实例对象共享一个值,可以通过类名或实例对象访问;而实例属性属于实例对象私有的属性,每个实例对象都有自己的值,只能通过实例对象访问。在实际开发中,需要根据实际情况选择类属性和实例属性的使用

2. 常用的类属性,方法装饰方式及用法

1. @property

将一个方法转换成属性,可以像访问属性一样访问。

class MyClass:
    def __init__(self, value):
        self._x = value
    
    @property
    def x(self):
        return self._x
    
c = MyClass(5)
print(c.x)  # 输出5

2. @classmethod

将一个方法声明为类方法,用类名调用。

class MyClass:
    x = 0
    
    @classmethod
    def classmethod(cls):
        cls.x += 1
        return cls.x
    
print(MyClass.classmethod())  # 输出1
print(MyClass.classmethod())  # 输出2

3. @staticmethod

将一个方法声明为静态方法,可以不需要实例化对象就能够调用。

class MyClass:
    @staticmethod
    def staticmethod():
        return "This is a static method."
    
print(MyClass.staticmethod())  # 输出"This is a static method."

4. @get.setter

用于设置属性值的方法,必须定义在@property方法下面。

class MyClass:
    def __init__(self, value):
        self._x = value
    
    @property
    def x(self):
        return self._x
    
    @x.setter
    def x(self, value):
        self._x = value * 2
    
c = MyClass(5)
print(c.x)  # 输出5
c.x = 10
print(c.x)  # 输出20

5. @get.deleter

用于删除属性的方法,必须定义在@property方法下面。

class MyClass:
    def __init__(self, value):
        self._x = value
    
    @property
    def x(self):
        return self._x
    
    @x.deleter
    def x(self):
        del self._x
    
c = MyClass(5)
print(c.x)  # 输出5
del c.x
# print(c.x)  # AttributeError: 'MyClass' object has no attribute '_x'

6. @cached_property

缓存属性,只计算一次,后续访问直接返回缓存值。

from cached_property import cached_property

class MyClass:
    @cached_property
    def x(self):
        print("Calculating x.")
        return 5
    
c = MyClass()
print(c.x)  # 输出Calculating x. 5
print(c.x)  # 输出5

7.@lazy_attribute

在第一次访问该属性时才进行计算,之后返回缓存值。

from lazy_object_proxy import Proxy

class MyClass:
    def __init__(self):
        self._my_property = Proxy(self.calculate_my_property)

    def calculate_my_property(self):
        print("Calculating my_property!")
        return 100

    @property
    def my_property(self):
        return self._my_property

my_class = MyClass()
print(my_class.my_property) # Output: Calculating my_property! 100
print(my_class.my_property) # Output: 100

二. 面向对象 - 类方法,静态方法,实例方法

1. 实例方法:

在Python中,类中的所有函数默认都是实例方法,实例方法是将self作为第一个参数的方法,它可以通过实例化一个对象来调用,它可以访问实例中的数据,也可以修改实例中的数据,最常用的方法之一。

示例代码

class MyClass:
    def my_instance_method(self, arg1, arg2):
        # 实例方法的代码
        pass

instance = MyClass()
instance.my_instance_method(arg1, arg2)

2. 类方法:

类方法是将cls作为第一个参数的方法,它可以通过类名或对象名来调用,也可以修改类变量,但是它不能访问实例变量,类方法使用@classmethod装饰器来定义。

示例代码

class MyClass:
    class_var = 0

    @classmethod
    def my_class_method(cls, arg1, arg2):
        # 类方法的代码
        cls.class_var += 1
        pass

MyClass.my_class_method(arg1, arg2)

3. 静态方法:

这种方法也是类成员方法,但它们不需要访问类或实例的上下文。静态方法可以像普通函数一样被调用,没有默认的参数。
静态方法不需要传递任何参数,它与类和实例无关,可以使用类名或对象名来调用,因此静态方法不能访问实例变量或类变量,静态方法使用@staticmethod装饰器来定义。

class MyClass:
    @staticmethod
    def my_static_method(arg1, arg2):
        # 静态方法的代码
        pass

MyClass.my_static_method(arg1, arg2)

三. 总结:

  • 实例方法是最常用的方法类型,只能被实例调用,第一个参数是self
  • 类方法和静态方法都是类成员方法,可以通过类或实例调用;
  • 类方法第一个参数是cls,表示当前类对象;
  • 静态方法没有默认参数,类的上下文不会传递给它。

以上就是关于python中面向对象的属性,类方法,静态方法,实例方法的区别及用法详解,希望对你有所帮助,请不吝你的三连,谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/920624.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java八股文面试[数据结构]——集合框架

Java集合体系框架 Java集合类主要由两个根接口Collection和Map派生出来的。 Collection派生出了三个子接口: Map接口派生: Map代表的是存储key-value对的集合,可根据元素的key来访问value。 因此Java集合大致也可分成List、Set、Queue、Map…

赋能道路交通场景,九州未来助力建成广西交科车路协同智能网联示范园区

智慧高速车路协同需要更加稳固的技术基座 智慧高速是中国高速公路建设的热点之一,车路协同又是未来智慧高速建设的核心内容。高速公路运行环境相对简单、主体权责清晰、路侧机电设施齐全,具备开展车路协同创新示范的良好条件。 广西交科集团&#xff0…

使用element-plus组件,默认显示英文 转换为中文

最近在边写项目边学习vue3 所以这几天没有更新 找机会把vue3的知识也统计一下吧 先说今天遇到的问题 最近做项目的时候使用element-plus分页组件时发现&#xff0c;显示的不是中文的了&#xff0c;是英文的 解决方法 在app.vue里面配置 <template><el-config-provi…

【ES】笔记-生成器函数与调用

function* function* 这种声明方式 (function关键字后跟一个星号&#xff09;会定义一个生成器函数 (generator function)&#xff0c;它返回一个 Generator 对象。 function * gen(){console.log("heloo generator")}如何调用呢&#xff1f;先看下里面的内容 返回…

Dockerfile快速搭建自己专属的LAMP环境,生成镜像lamp:v1.1,并推送到私有仓库

环境&#xff1a; CentOS 7 Linux 3.10.0-1160.el7.x86_64 具体要求如下&#xff1a; &#xff08;1&#xff09;基于centos:6基础镜像&#xff1b; &#xff08;2&#xff09;指定作者信息&#xff1b; &#xff08;3&#xff09;安装httpd、mysql、mysql-server、php、ph…

【锐捷】OSPF 多区域配置

【实验名称】 配置 OSPF 多区域。 【实验目的】 配置 OSPF 多区域&#xff0c;理解 OSPF 层次型网络的特点。 【背景描述】 本实验拓扑图中有 3 台路由器&#xff0c;路由器在区域 0 和区域 1 中&#xff0c;路由器 B 在区域 0 和区域 30&#xff0c; 路由器 C 在区域 30。 【需…

简单着色器编写(下)

函数部分介绍完了&#xff0c;最后来介绍一下main函数中的部分。 std::string vertexShader "#version 330 core\n" "\n" "layout(location0)in vec4 position;" "\n" "void main()\n" "{\n&…

day43参与通信的服务器

1.题目描述 这里有一幅服务器分布图&#xff0c;服务器的位置标识在 m * n 的整数矩阵网格 grid 中&#xff0c;1 表示单元格上有服务器&#xff0c;0 表示没有。 如果两台服务器位于同一行或者同一列&#xff0c;我们就认为它们之间可以进行通信。 请你统计并返回能够与至少…

数据分析实战│时间序列预测

时间序列预测问题是一类常见的数据分析问题。数据中往往包含时间标签,这类问题往往根据过去一段时间的数据,建立能够比较精确地反映序列中所包含的动态依存关系的数学模型,并对未来的数据进行预测。 01、问题描述及数据挖掘目标 本案例给出二战时期的某气象站温度记录值,通…

Terraform(二)

Terraform实践 1. Terraform Docker Example1.1 Install Terraform1.2 Verify the installation1.3 Enable tab completion1.4 Quick start tutorial To deploy infrastructure with Terraform: Scope - Identify the infrastructure for your project.Author - Write the con…

【校招VIP】前端校招考点之行内/块级元素

考点介绍&#xff1a; 行内元素会在一条直线上排列&#xff08;默认宽度只与内容有关&#xff09;&#xff0c;都是同一行的&#xff0c;水平方向排列。块级元素各占据一行&#xff08;默认宽度是它本身父容器的100%&#xff08;和父元素的宽度一致&#xff09;&#xff0c;与内…

抖音书单背景图制作怎么做?分享两个制作小妙招

相信屏幕前的小伙伴今天有刷抖音吧&#xff01;由于迎合受众对碎片化传播的需求&#xff0c;抖音也成为了当下最流行的短视频应用之一&#xff0c;在抖音上分享书单已经成为了一种流行的趋势&#xff0c;而制作一张吸引人的书单背景图是很重要的。在本文中&#xff0c;我们将分…

Python Web开发技巧X

目录 select_related 和 prefetch_related 生成器对象的三种创建方式 classmethod和staticmethod __class__属性 python创建一个类会依次去调用哪些方法 __new__和__init__实现单例模式的饿汉式和懒汉式 select_related 和 prefetch_related select_related 和 prefetch_…

HTML中SCRIPT 标签中的那些属性

在HTML中&#xff0c; <script> 标签用于嵌入或引用JavaScript代码。 在 <script> 标签中&#xff0c;有两个属性可以用来控制脚本的加载和执行方式&#xff1a; async 和 defer 。 当然这也是常见的一道面试题&#xff0c; async 和 defer 的作用和区别。 asy…

【IO流中的字节流(InputStream)(OutputStream)】

字符集 美国人发明计算机 要将他们的字符存入计算机&#xff08;英文字母、数字、标点、特殊字符&#xff09; 给字符进行编号&#xff0c;组成了一张ASCII码表&#xff08;美国信息交换标准代码&#xff09;&#xff0c;一共包含128个字符 该码表以1个字节存储1个字符&#xf…

Java 实现 国密SM4/ECB/PKCS7Padding对称加密解密

Java 实现 国密SM4/ECB/PKCS7Padding对称加密解密&#xff0c;为了演示方便本问使用的是IntelliJ IDEA 2022.1 (Community Edition)来构建代码的 1、pom.xml文件添加需要的jar <?xml version"1.0" encoding"UTF-8"?> <project xmlns"htt…

1002 Business

要解这道题目&#xff0c;感觉最关键的因素就是找到第 件任务最晚开始的时间 。这个看似简单&#xff0c;但是对建模的功底要求相当高。我一开始就把 当成了 &#xff0c;但其实不是的。后者就相当于把第 件任务锁死在最后面完成&#xff0c;但其实是允许放在之前完成的&am…

springboot2+redis 订阅发布,解决接收消息累计线程到内存溢出,使用自定义线程池接收消息

pom 添加redis <!-- redis 缓存操作 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 发布消息 import lombok.extern.slf4j.Slf4j; import o…

FPGA原理与结构——FIFO IP核原理学习

一、FIFO概述 1、FIFO的定义 FIFO是英文First-In-First-Out的缩写&#xff0c;是一种先入先出的数据缓冲器&#xff0c;与一般的存储器的区别在于没有地址线&#xff0c; 使用起来简单&#xff0c;缺点是只能顺序读写数据&#xff0c;其数据地址由内部读写指针自动加1完成&…

DC电源模块关于输入电压范围

BOSHIDA DC电源模块关于输入电压范围 DC电源模块是一种常用的电源供应设备&#xff0c;其主要作用是将交流电转化为直流电&#xff0c;以供电子设备使用。在DC电源模块的使用过程中&#xff0c;输入电压范围是一个非常重要的参数&#xff0c;它关系到模块的稳定性、可靠性以及…