首页 > 编程语言 >Python面向对象,类属性,实例属性,类方法,实例方法,静态方法的区别及用法详解

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

时间:2024-02-28 12:01:05浏览次数:26  
标签:静态方法 self 实例 MyClass 方法 class 属性

一. 前言

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

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

1. 区别

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

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

2. 示例代码

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 之后,我们分别访问了它们的实例属性和类属性,然后我们修改了类属性的值,并且分别访问了两个实例的类属性值,最后打印了每个实例的属性值。

运行结果如下

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

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

3. 总结

  • 类属性是一个类的全局变量,所有实例对象共享一个值,可以通过类名或实例对象访问,此外需要注意不同的修改方式可能会影响类属性的最终输出结果。
  • 实例属性属于实例对象私有的属性,每个实例对象都有自己的值,只能通过实例对象访问。

在实际开发中,需要根据实际情况选择类属性和实例属性的使用

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

8. @abstractmethod

@abstractmethod是Python语言中用于实现抽象方法的装饰器。当一个方法被@abstractmethod装饰时,它就成为了一个抽象方法,必须在子类中被实现,否则子类将无法实例化。

使用@abstractmethod装饰器可以将一个方法标记为抽象方法。抽象方法通常被声明在抽象类中,抽象类是一种不能被实例化的类,只能被继承。子类继承抽象类时必须实现它的抽象方法。

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius * self.radius

#s1 = Shape() # This will raise TypeError

r = Rectangle(5, 10)
print(r.area())

c = Circle(7)
print(c.area())
 

在上述示例中,我们定义了一个抽象类Shape,它包含一个抽象方法area()。我们还定义了两个子类RectangleCircle,它们都继承自Shape类,并实现了area()方法。在这个例子中,我们不能实例化Shape类,但可以实例化RectangleCircle类。每个实例都可以使用自己相应的area()方法计算面积。

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

1. 三者主要区别:

1. 类方法:

使用@classmethod装饰器进行修饰,第一个参数默认为cls,表示类本身。类方法是可以被类和类的实例对象调用的。在类方法中不能访问实例属性和实例方法,因为它不依赖任何实例对象,而是依赖类本身,通常用于创建类对象或者对类属性的操作。

2. 实例方法:

实例方法没有任何特殊的修饰器,第一个参数默认为self,表示实例本身。实例方法只能被实例对象调用,因为它依赖于实例对象。实例方法可以访问实例对象的属性和其他实例方法。

3. 静态方法:

使用@staticmethod装饰器进行修饰,它不需要表示自身对象的selfcls参数。静态方法是类的工具包,它与类和实例对象没有任何关系,通常用于工具函数或类的初始化操作。

2. 另外介绍类方法和实例方法两种类型区别:

  • 类方法使用@classmethod装饰器修饰,而实例方法没有。
  • 类方法的第一个参数是类对象(cls),而实例方法的第一个参数是实例对象(self)。
  • 类方法可以直接通过类名调用,而实例方法必须通过实例对象调用。
  • 类方法对于所有实例都是一样的,而实例方法对于每个实例都可能会不同。
  • 类方法通常用于创建、修改、查询类属性和类状态的操作,而实例方法通常用于操作实例属性和实例状态的操作。
  • 类方法可以访问类属性,但不能访问实例属性。而实例方法可以访问实例属性和类属性。

在使用类方法和实例方法时,需要根据具体的业务需求来选择使用哪一种方法。

3. 示例代码说明解释

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中面向对象的属性,类方法,静态方法,实例方法的区别及用法详解,希望对你有所帮助,请不吝你的三连,谢谢!

 

2024-02-28 11:54:38【出处】:https://johnsonchen.blog.csdn.net/article/details/132459157

=======================================================================================

标签:静态方法,self,实例,MyClass,方法,class,属性
From: https://www.cnblogs.com/mq0036/p/18039886

相关文章

  • Uniapp商城小程序源码+运行实例+下载资源包全开源
    商城小程序源码是一种可以用来开发商城类小程序的代码文件或项目,它包含了商城小程序的基本功能和界面设计等内容。通过使用商城小程序源码,开发者可以节省开发时间和成本,快速构建和定制自己的商城小程序。源码通常包括用户登录、商品浏览、购物车、订单管理、支付功能等,以满足......
  • SQL Server隐藏实例会导致Alwasy on手动故障转移时报error 26
    SQLServer的配置管理器(SQLServerConfigurationManager)下,你可以隐藏数据库实例,设置了隐藏实例后,SQLServerBrowser不会对此服务器实例的相关信息做出响应,(当SQLServer客户端请求SQLServer资源时,客户端将使用1434端口向服务器发送一条UDP消息。SQLServer浏览器将......
  • Spring系列之(二)Spring基于XML的IOC实例
    Spring基于XML的IOC实例将改进后的工厂模式通过Spring来实现,解析配置文件、创建仓库,将对象存入仓库的过程都由Spring来做,我们只需要配置好配置文件,获取仓库中的对象即可1.在pom中引入Spring环境<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.o......
  • C# 简单反射加载 DLL 实例
    //反射判断是否位某个类型publicboolIsSubclassOf(thisTypetype,TypebaseType){//如果type不是null并且baseType是一个类(非接口)if(type!=null&&baseType.IsClass){returntype.IsSubclassOf(baseType);}//或者如果baseType是......
  • 使用cmd命令行(.NET Core CLI)来启动ASP.NET Core 应用程序的多个实例
    本章主要和大家分享下如何使用cmd命令行(.NETCoreCLI)来启动ASP.NETCore应用程序的多个实例,以此来模拟集群。.NETCore命令行接口(CLI)工具是用于开发、生成、运行和发布.NETCore应用程序的跨平台工具链。CLI命令结构包含驱动程序(“dotnet”)和命令,还可能包含命令参数......
  • makefile 实例: 编译libxyz.so 和 abc可执行文件。
    .PHONY:cleanallalldepall:alldepOBJDIR=Object###libxyx.so###TARGET_LIB_XYZ=libxyz.soTARGET_LIB_XYZ_OUTPUT=$(OBJDIR)/$(TARGET_LIB_XYZ)LDFLAGS+=-ltelux_wlan-lnl-3-lnl-genl-3LDFLAGS+=-L$(SDKTARGETSYSROOT)/lib-L.-rdynamicCFLAGS+=-I$(S......
  • JavaScript 实现JSON 对象数组以某个属性进行分组处理
    JavaScript实现JSON对象数组以某个属性进行分组处理要在JavaScript中对JSON对象数组的某个属性进行分组处理,你可以使用一个对象来存储分组后的结果。下面是一个简单的示例,演示了如何对JSON对象数组中的某个属性进行分组处理:假设我们有一个JSON对象数组,每个对象都有ca......
  • 面向对象编程的绑定方法、掩藏属性、装饰器
    一、绑定方法1、绑定给类的方法(@classmethod)12345678910111213141516171819class Oracle():    def __init__(self,ip,port):        self.ip = ip        self.port = port     @classmethod  #该方法......
  • Vue学习笔记16--监视属性watch + 深度监视 + 监视简写
    监视属性watch示例一:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>计算属性</title&......
  • 说一下flex的属性
    flex-grow项目的放大比例,默认为0,即如果存在剩余空间,也不放大。flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。负值对该属性无效。flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(mainsize)。浏览器根据这个属性,计算主轴是否有多余空间。它......