• 0
  • 0
分享
  • Python类的多种方法,你分得清吗?——软件测试圈
  • 曼倩诙谐 2022-11-28 11:18:21 字数 3387 阅读 1348 收藏 0

  小编已经在内测抽奖系统了,快来填问卷、赢礼品吧!链接:http://vote.51testing.com/   (本次礼包好物多多:大容量马克杯、畅销测试书籍)


  在初学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(cls, 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啥也不传,需要几个参数就要传几个参数。



作者:王小健    

来源:http://www.51testing.com/html/58/n-7793858.html

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •   最近在看一些底层的东西。driver翻译过来是驱动,司机的意思。如果将webdriver比做成司机,竟然非常恰当。  我们可以把WebDriver驱动浏览器类比成出租车司机开出租车。在开出租车时有三个角色:  · 乘客:他/她告诉出租车司机去哪里,大概怎么走。  · 出租车司机:他按照乘客的要求来操控出租车。  · 出租车:出租车按照司机的操控完成真正的行驶,把乘客送到目的地。  在WebDriver中也有类似的三个角色:  · 自动化测试代码:自动化测试代码发送请求给浏览器的驱动(比如火狐驱动、谷歌驱动)。  · 浏览器的驱动:它来解析这些自动化测试的代码,解析后把它们发送给浏...
            1 0 1953
            分享
          •   美国商务部长吉娜-雷蒙多(Gina Raimondo)周二表示,没有证据表明中国制造商华为可以大批量生产采用先进芯片的智能手机。  华为最近开始销售一款名为Mate 60 Pro的手机,分析师认为这款手机的芯片是由中芯国际(0981.HK)利用突破性技术制造的。  雷蒙多在美国众议院听证会上提到一种先进芯片时说:"我们没有任何证据表明他们可以大规模生产7纳米(芯片)。"  美国商务部本月早些时候表示,它正在努力获取更多信息,以"了解"可能违反贸易限制的芯片的"特性和成分"。雷蒙多在众议院科学委员会听证会上表示,她对华为智能手机的先...
            0 0 870
            分享
          •   苹果在一份支持文件中宣布,它将在2023年7月26日下线"我的照片流"。这项服务已经提供了十多年,允许用户通过互联网在苹果设备上同步他们的照片。这项图片同步服务最初被称为"照片流",是在2011年WWDC期间宣布的。它可以自动从iPhone或iPad上传多达1000张最近点击的照片到iCloud。  上传的媒体在云端停留长达30天,并自动下载到使用同一苹果ID的其他设备上,包括Mac和WindowsPC。同样,当年在Mac上导入iPhoto应用的新图片也会被上传到云端,并在不同设备间同步。  最终,在上传所有照片、视频以及对媒体进行编辑的iCloud...
            0 0 863
            分享
          • 我们测试过程中,常常遇到提交的bug单,开发定位时发现无法定位,或者我们自己发现了bug,想截图或者复制日志时,发现无法复现了,针对这些情况,本文将总结一些bug复现的思路,供参考。1、重复执行仔细回忆测试时的执行步骤,尽量还原所有步骤,不要漏掉任何一个细节,故障可能是特定的执行顺序导致;仔细回忆测试时的所有配置,是否是特定的配置导致的故障?2、 是否网络问题?对于前后端交互类的bug,如果不能复现,要充分怀疑是否是网络不良导致的问题,可拔出网线试验一下,看能否复现。3、是否特定数据造成?可以回忆当时测试时上传的附件是什么?是否做了什么特殊输入,如特殊字符,特别长的字符等。4、是否自己测试机器...
            0 1 1983
            分享
          •   相信很多测试人员在进入职场时都面临过一个问题:大厂VS创业公司,到底该如何进行选择呢?  别着急,让我们先看看两者测试相关的区别。  大厂和创业公司,不管从测试流程、测试角色划分、测试用例设计还是使用的测试工具上,都是有比较明显的区别的。笔者在大厂和创业公司分别呆过三年,今天简单来总结下大厂和创业公司测试流程的区别。  大厂的测试流程  大厂的测试流程,每一步都有会议记录,需求变更严格走变更流程,会输出规格书、prd和原型图以及设计图。  创业公司的测试流程  创业公司的测试流程,一个会议会同时确认好几个事情,需求变更看大小,不麻烦就直接做上去了,基本只有原型图和设计图。  看完梳理的流程...
            0 0 930
            分享
      • 51testing软件测试圈微信