python中的类方法、静态方法、实例方法

python创建类的流程

要想真正的了解类方法、实例方法和静态方法的区别。首先要搞清楚python在实例化中的过程。
首先我们编写一个Person类。

class Person():
    country = 'china'

    def __init__(self):
        self.name = 'root'
        self.age = 30

    # 实例方法
    # 当你调用实例方法的时候,python解释器会自动将实例对象传给self
    def test(self):
        self.country = 'xxx'
        print("实例方法", self)

    # 静态方法
    @staticmethod
    def test2():
        print("静态方法")

    # 类方法
    # 当你调用类方法的时候,python解释器会将类对象传递给self
    @classmethod
    def test3(cls):
        cls.country = 'ddddd'
        print("类方法", cls)

一个类已经创建好了,下面当我们执行

p = Person()

的时候,python是怎么工作的呢?

  1. 调用__new__方法申请一个内存空间。
  2. 调用Person中的__init__方法,对__new__方法申请到的内存空间进行初始化。
  3. 这里我们把Person称之为类对象,而p我们称之为实例对象。
  4. 那么在内存中,就如下图:
    在这里插入图片描述
    python会另外开启一个内存空间给实例对象使用。在这个实例对象中,仅仅拥有__init__定义的属性和__class___等一些魔法属性。
    而类对象中定义的方法在实例对象的空间中是没有的。实例对象中有一个__class__属性,这个属性指向创建该实例对象的类对象。当实例对象想要调用类中定义的方法的时候,会通过__class__进行调用。

有几个重点需要知道

  • 实例对象中不存在类对象中定义的方法

    class Person():
        country = 'china'
    
        def __init__(self):
            self.name = 'root'
            self.age = 30
    
        # 实例方法
        # 当你调用实例方法的时候,python解释器会自动将实例对象传给self
        def test(self):
            self.country = 'xxx'
            print("实例方法", self)
    
        # 静态方法
        @staticmethod
        def test2():
            print("静态方法")
    
        # 类方法
        # 当你调用类方法的时候,python解释器会将类对象传递给self
        @classmethod
        def test3(cls):
            cls.country = 'ddddd'
            print("类方法", cls)
    
    p = Person()
    print(p.__dict__)
    print(Person.__dict__)
    

    看一下结果:

    {'name': 'root', 'age': 30}
    {'__module__': '__main__', 'country': 'china', '__init__': <function Person.__init__ at 0x03AB9108>, 'test': <function Person.test at 0x03AB9390>, 'test2': <staticmethod object at 0x03AB8E10>, 'test3': <classmethod object at 0x03ABA5B0>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
    

    通过__dict__,我们可以看到在实例对象中,仅仅有的是通过__init__初始化的内容。

  • 实例对象通过__class__调用类对象中方法和属性

我们知道,刚刚类中定义的country是类属性,那么如果实例对象想要修改这个类属性,就需要通过__class__进行调用并修改。

还是刚才那个类,我们添加两个实例方法进去,通过对类属性的修改做一个验证。

	# 通过self直接修改
    def change1(self):
        self.country = 'xxx'

    # 通过__class__修改
    def change2(self):
        self.__class__.country = 'xxx'

然后分别进行调用:

p = Person()
p1 = Person()

print("self直接修改")
print("*"*50)
p.change1()
print(p.country)
print(p1.country)
print(p.__dict__)
print("*"*50)

print()

p = Person()
p1 = Person()

print("__class__直接修改")
print("*"*50)
p.change2()
print(p.country)
print(p1.country)
print(p.__dict__)
print("*"*50)

结果:

self直接修改
**************************************************
xxx
china
{'name': 'root', 'age': 30, 'country': 'xxx'}
**************************************************

__class__直接修改
**************************************************
xxx
xxx
{'name': 'root', 'age': 30}
**************************************************

可以看到,如果不通过__class__修改类属性,那么仅仅是为实例对象添加了一个新的属性,而没有改变类属性的值。而通过__class__才真正的引用到了类属性。而我们在直接使用实例对象去访问类属性的时候是可以访问的,原因是因为当python发现实例对象中没有这个属性的时候,就会自动调用__class__去类对象中寻找。


类方法、实例方法、静态方法

在了解了类的创建以及内存分配以后。我们就可以来了解一下类中的方法。
还是我们定义的这个类:

class Person():
    country = 'china'

    def __init__(self):
        self.name = 'root'
        self.age = 30

    # 实例方法
    def test(self):
        self.country = 'xxx'
        print("实例方法", self)

    # 静态方法
    @staticmethod
    def test2():
        print("静态方法")

    # 类方法
    @classmethod
    def test3(cls):
        cls.country = 'ddddd'
        print("类方法", cls)

首先要弄清楚实例方法中的self和类方法中的cls指的是什么东西?
我们弄一个例子看一下:

p = Person()
# 查看self
p.test()
Person.test(p)

Person.test3()
p.test3()

结果:

实例方法 <__main__.Person object at 0x0BAD41F0>
实例方法 <__main__.Person object at 0x0BAD41F0>
类方法 <class '__main__.Person'>
类方法 <class '__main__.Person'>

由此我们可以知道self指向的是实例对象所在的内存空间,而cls指向的是类对象。当我们调用实例方法的时候,python解释器会自动将实例对象传入self,而当我们调用类方法的时候,python解释器则会将类对象存入到cls中。

那么实例方法和类方法有什么区别呢?
由于实例方法传入的是实例对象,因此当我们对一些实例属性进行操作的时候,一般就构造实例方法。而当我们对类属性进行操作的时候就使用类方法。还是刚才的例子,更改country的值。这次我们使用类方法就会轻松很多:

@classmethod
    def test3(cls):
        cls.country = 'ddddd'
        print("类方法", cls)

同理,当我们对实例属性进行操作的时候,使用实例方法也就很方便。
除此之外,类方法和实例方法还有一个区别就是,当你所创造的这个类被当做一个模块导入的时候。如果要调用实例方法,那么就必须要进行实例化。实例化就会占用一些内存空间,当你仅仅是想使用这个类中的一些方法而并不想要实例化的时候,就可以定义一个类方法。

静态方法的作用则是,当你定义了一个类,需要构造一种方法,但是又不需要为这个方法传递类对象或者实例对象,仅仅想当做这个类中的一个普通方法的时候,就可以定义一个静态方法。(比如一些类的说明等)

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值