51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 510|回复: 0
打印 上一主题 下一主题

Python类的多种方法你知道多少

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-11-15 16:06:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在初学Python过程中,会遇到这样的概念,一个类下面会有多个方法,有的叫类方法、有的叫静态方法,还有的叫实例方法。当调用他们的时候,不免会有点蒙圈,那么他们之间的区别是什么呢?


  和类属性一样,类方法可以进行细致地划分为类方法、实例方法和静态方法。


  表象区别就是:


  类方法前用@classmethod修饰


  静态方法前用@staticmethod修饰


  不加任何修饰的就是实例方法(普通方法)


  用法区别


  实例方法

  也是普通方法,实例方法是我们最常用的方法,它定义时最少要包含一个self参数,用于绑定调用此方法的实例对象(所谓绑定,即用实例调用的时候,不需要显式的传入)。

  换句话说,当实例调用方法的时候,会默认将实例本身传入到这个参数self,而当类直接调用时,因为本身类型是一个class,不是实例对象,所以报错。


  如果非要用类直接调用,需要手动传入一个实例作为第一个参数。注意:若随便传入一个字符串的话,也不会报错,但是会造成程序紊乱,因此不推荐这种调用方式。


  用如下这段代码举例说明:


class A(object):


    def instance_method(self, X):


        print(f'instance_method :{X} : {self}')



a = A()


A.instance_method('x')


A.instance_method(a, 'x')  


A.instance_method('strs', 'x')


a.instance_method('a')




  代码中 instance_method 为实例方法,而第6行类A调用了此方法,而实例方法默认传入的应该是实例,而不是类,因此将x当做实例传给了默认的self,此时实例方法还缺少一个参数没有传入,导致报



错:TypeError: instance_method() missing 1 required positional argument: 'x'。

  第7行纠正了第6行的做法,传入了实例a,且传入了一个参数x,所以不会报错,self就是A的实例a。


  第8行将字符串代替实际的实例a传入self,虽不会报错,但是对于程序毫无价值,不推荐这样使用,没有意义。


  第9行是最常用的方法,实例a调用了实例方法,默认将实例a传入了self,再将参数x传入了X,完整实现了调用。


  本地方法


  就当做实例方法的一种吧,好奇心的驱使,如果实例方法没有添加self这个参数呢,为了区分,我们且叫他“本地方法”。所谓本地,也就是实例无法调用,只能类自己调用。

class A(object):


    def local_method():


        print(f'local_method')



    def local_method2(strs):


        print(f'local_method2')



a = A()


a.local_method()


a.local_method2()


A.local_method()



  如上代码,第2行的local_method()就是个本地方法,而此时在第9行实例a调用这个本地方法的时候,由于程序会默认将实例a传入参数self,但是本地方法没有写self,因此报错:TypeError:


A.local_method() takes 0 positional arguments but 1 was given。

  再看第5行的实例方法,为什么叫实例方法,明明没有self啊?这里要特别说明下,self只是约定俗成的写法,实际上随便写个什么字符串都可以的。因此第10行实例a调用实例方法,不会报错,程序正常



执行。

  第11行类A调用本地方法,也是不会报错的。但如果类A调用实例方法就和第一节讲的报错了。


  类方法


  类方法有一个特点,就是这个方法必须要有@classmethod来修饰。和实例方法类似,至少也要传一个参数,约定俗称为cls,Python会自动将类本身绑定到这个参数上面。

  类方法通常使用类直接调用,也可以用实例调用(不推荐)。当实例调用的时候,Python会将实例的最底层类(即实例直接所属类)型传入cls参数中。


class A(object):


    name = 'I am Class A'



    @classmethod


    def class_method(c
ls, s):



        print(cls.name)  # 可以访问类成员print(cls.name)     # 可以访问类成员

        print(f"class_method : {cls} :: {s}")



class B(A):


    name = 'I am Class B'  



a = A()


b = B()


A.class_method('I am class')


a.class_method('I am instance')


B.class_method('I am B class')


b.class_method('I am b instance')




  如上代码,B类继承了A类,并复写了name属性,而此时A类中的方法就是类方法,有两个参数,一个是默认的类参数cls,还有一个普通入参。


  第14行,A类直接调用自己的类方法,默认将自己传入了cls,并将括号中的字符串传给了参数s,用得恰到好处。此时第6行打印“I am Class A”可以看出,cls确实是传的A。



  第15行用A的实例a调用类方法,会默认将a的直属类(也就是A)传到cls中,因此效果和A调用是一样的。

  第16行用继承类B调用的父类的类方法,既然是继承,那么程序传入的就是类B到cls中,由于B类中对name做了复写,因此第6行打印出来的就是“I am Class B”。


  第17行用继承类B的实例b调用的父类的类方法,按照上述规则,是传入的b的直属类到cls中,也就是将B传入了cls中,而不是A(这边要注意区别),因此和B调用是一样的。


  静态方法


  静态方法是使用@staticmethod修饰的方法,它不能访问任何类属性和类方法,因为它不含self或cls这些特殊参数,因此也无法访问类或实例中的成员。

  也就是说,Python没有给他绑定实例或者类,要想使用,只能当参数来传,所以在静态方法中的入参都是普通参数,严格来讲,上面说的本地方法应该也要写成静态方法。


class A(object):


    @staticmethod


    def static_method(a, b):


        print(f"static_method : {a} + {b}")



a = A()


A.static_method('aa', 'bb')


a.static_method('aa', 'bb')




  如上代码中,尽管第7行类A调用了方法,但是由于是静态方法,访问不了类属性,因此不会将类A传入所谓的cls中,静态方法中也没有cls这个参数,因此它的参数都是普通入参。


  第8行的实例调用也是和A一样的效果。


  所以逻辑上讲,类方法应当只被类调用,实例方法只被实例调用,静态方法两者都能调用,主要区别在于参数传递上的区别。


  实例方法悄悄传递的是self引用作为参数,而类方法悄悄传递的是cls引用作为参数。


  要记住几点


  1.实例调用实例方法和本地方法时,Python默认将实例本身作为第一个参数传入。

  2.实例调用类方法时,Python默认将实例的最底层类作为第一个参数传入。


  3.实例调用静态方法时,Python啥也不传,需要几个参数就要传几个参数。


  4.类调用类方法时,Python默认将类本身作为第一个参数传入。


  5.类调用非类方法时,Python啥也不传,需要几个参数就要传几个参数。





分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-4-27 09:08 , Processed in 0.069697 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表