深入了解Python 方法之类方法 & 静态方法


Posted in Python onAugust 17, 2020

写在之前

这几天的阅读量蜜汁低,是什么原因我也没搞清楚,如果你们觉得我哪里写的有问题,或者是哪里不好,欢迎后台或者微信告知我,先行谢过。

昨天的文章 详解类方法之绑定方法与非绑定方法 中写了方法中的绑定方法和非绑定方法,今天我们继续来学习剩下的「类方法」和「静态方法」。

类方法 & 静态方法

在开始之前,先让我们来看下面一段代码:

class Sample:
 language = "C++"
 def __init__(self):
 self.language = "python"

def get_class_attr(cls):
 return cls.language

if __name__ == "__main__":
 print("sample.language:",Sample.language)
 r = get_class_attr(Sample)
 print("get class attribute:",r)
 f = Sample()
 print("instance attribute:",f.language)

上述代码在类 Sample 中,定义了一个属性 language = “C++”,这个是「类属性」;在初始化方法中,又定义了 self.language = “python”,这个是「实例属性」。

知道了这个,我们然后来分析一下函数 get_class_attr(cls),在这个函数中参数用的是 cls,从函数体来看,要求它引用的对象应该具有属性 language,这说明,不是随随便便哪个对象都可以。很巧的是在前面定义的类 Sample 中就有 language 这个属性,于是在调用这个函数的时候,就直接将该类对象作为方法 get_class_attr() 的参数。

Sample.language 是要得到类属性的值,get_class_attr(Sample) 所返回的就是类 Sample 的属性 Sample.language 的值,所以对于上述例子来说,前面两个 print() 函数打印的结果应该是一样的。

f = Sample() 则是创建了一个实例,然后通过 f.language 访问实例属性。所以对于上述的代码的运行结果如下所示:

sample.language:C++
get class attribute:C++
instance attribute:python

不知道经过我上述的解释你是否明白了,如果没明白,建议你再仔细对比一下上述的运行结果和分析的过程。

在上述的例子中,比较特殊的函数应该是 get_class_attr(cls),它是写在类的外面的,然而这个函数又只能调用前面写的那个类对象,因为不是所有对象都有那个特别的 language 属性,这种函数写在外面不利于后期的维护,我们应该避免这种情况的发生,而避免的方法就是把函数和类写在一起,所以就有了下面这种写法:

class sample:
 language = "C++"
 def __init__(self):
 self.language = "python"

 @classmethod
 def get_class_attr(cls):
 return cls.language

if __name__ == "__main__":
 print("sample.language:",sample.language)
 r = sample.get_class_attr()
 print("get class attribute:",r)
 f = sample()
 print("instance attribute:",f.language)
 print("instance get_class_str:",f.get_class_attr())

在上面这个修改的代码中,出现了 @classmethod,这是一个装饰器,我们在函数的那部分讲到过。这里需要我们注意的是,@classmethod 所装饰的方法的参数中,第一个参数不是 self,这个和我们常规认识中的类的方法有所区别。这里使用了参数 cls,这是习惯的写法,当然用其它的也可以。让我们来看一下运行的结果:

sample.language:C++
get class attribute:C++
instance attribute:python
instance get_class_str:C++

通过上面的运行结果我们可以看到,不管是通过类还是实例来执行 get_class_attr() 得到的结果都是类属性的值,这说明装饰器 @classmethod 所装饰的方法,它的参数 cls 引用的对象是类对象 Sample。

至此,「类方法」 的定义就出来了:类方法,就是在类里面定义的方法。该方法由装饰器 @classmethod 装饰,其第一个参数 cls 引用的是这个类对象,即将类本身作为作为引用对象传到这个方法里。

知道了类方法以后,我们可以用同样的思路理解另一个方法 「静态方法」,我们还是先来看一段代码:

import random

def judge(n):
 num = random.randint(1,100)
 return num - n > 0

class Sample:
 def __init__(self,name):
 self.name = name

 def get_name(self,age):
 if judge(age):
  return self.name
 else:
  return "the name is stupid"

if __name__ == "__main__":
 s = Sample('rocky')
 name = s.get_name(23)
 print(name)

先看一下上面的代码,类 Sample 里面使用了外面的函数 judge(n),这种类和函数的关系也是因为相互关联,所以后期的程序维护可能会出问题,于是为了便于维护,我们同样对程序进行了修改:

import random

class Sample:
 def __init__(self,name):
 self.name = name

 def get_name(self,age):
 if self.judge(age):
  return self.name
 else:
  return "the name is stupid"
 @staticmethod
 def judge(n):
 num = random.randint(1,100)
 return num - n > 0

if __name__ == "__main__":
 s = Sample('rocky')
 name = s.get_name(23)
 print(name)

同样是经过修改优化,将原来在类外面的函数放到了类里面。但是这不是简单的移动,还要在函数的前面加上 @staticmethod 装饰器,并且要注意的是,虽然这个函数在类的里面,但是跟别的方法是不一样的,它的第一个参数也不是 self,当我们要使用它的时候,可以通过实例调用,比如 self.judge(n),也可以通过类调用这个方法,比如 sample.select(n)。

从上面的程序可以看出,尽管 judge(n) 位于类里面,但它确实一个独立的方法,与类本身没有关系,仅仅是为了免除前面所说的后期维护上的麻烦。但是它也有存在的道理,上面的例子就是一个典型的说明。

所以「静态方法」的定义也就出来了:在类的作用域里面,前面必须要加上一个 @staticmethod 装饰器,我们将这种方法命名为静态方法。

写在之后

方法是类的重要组成部分,本章所讲的类方法和静态方法让我们在使用类的时候有了更加便利的工具。

「方法」的这一块到这里就补充完了,之后我们将继续学习 OOP 的剩下两个特征:「多态」和「封装」,敬请期待。

如果你觉得本篇文章让你有所收获,欢迎点赞转发,你的支持是对我码字最大的动力,分享永远在路上,我们一起加油。

The end。

以上就是深入了解Python 方法之类方法 & 静态方法的详细内容,更多关于python 类方法和静态方法的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python实现得到一个给定类的虚函数
Sep 28 Python
Python类定义和类继承详解
May 08 Python
Python断言assert的用法代码解析
Feb 03 Python
python 使用matplotlib 实现从文件中读取x,y坐标的可视化方法
Jul 04 Python
python opencv调用笔记本摄像头
Aug 28 Python
jenkins配置python脚本定时任务过程图解
Oct 29 Python
Pycharm debug调试时带参数过程解析
Feb 03 Python
pyautogui自动化控制鼠标和键盘操作的步骤
Apr 01 Python
python实现凯撒密码、凯撒加解密算法
Jun 11 Python
python 实现音频叠加的示例
Oct 29 Python
Python操作PostgreSql数据库的方法(基本的增删改查)
Dec 29 Python
用PYTHON去计算88键钢琴的琴键频率和音高
Apr 10 Python
详解如何在PyCharm控制台中输出彩色文字和背景
Aug 17 #Python
python如何操作mysql
Aug 17 #Python
详解python 内存优化
Aug 17 #Python
浅谈如何使用python抓取网页中的动态数据实现
Aug 17 #Python
详解Python 中的容器 collections
Aug 17 #Python
Python 解析库json及jsonpath pickle的实现
Aug 17 #Python
Python实现爬取网页中动态加载的数据
Aug 17 #Python
You might like
php空间不支持socket但支持curl时recaptcha的用法
2011/11/07 PHP
PHP微信开发之二维码生成类
2015/06/26 PHP
PHP实现原生态图片上传封装类方法
2016/11/08 PHP
PHP将身份证正反面两张照片合成一张图片的代码
2017/04/08 PHP
PHP实践教程之过滤、验证、转义与密码详解
2017/07/24 PHP
PHP 实现人民币小写转换成大写的方法及大小写转换函数
2017/11/17 PHP
laravel 配置路由 api和web定义的路由的区别详解
2019/09/03 PHP
laravel5.6 框架邮件队列database驱动简单demo示例
2020/01/26 PHP
Javascript 调试利器 Firebug使用详解六
2009/07/05 Javascript
jQuery的初始化与对象构建之浅析
2011/04/12 Javascript
JavaScript实现生成GUID(全局统一标识符)
2014/09/05 Javascript
jQuery实现带分组数据的Table表头排序实例分析
2015/11/24 Javascript
AngularJS  $on、$emit和$broadcast的使用
2016/09/05 Javascript
浅析BootStrap Treeview的简单使用
2016/10/12 Javascript
NodeJS中的MongoDB快速入门详细教程
2016/11/11 NodeJs
微信小程序 跳转传参数与传对象详解及实例代码
2017/03/14 Javascript
微信小程序之购物车功能
2020/09/23 Javascript
vue组件学习教程
2017/09/09 Javascript
vue中tab选项卡的实现思路
2018/11/25 Javascript
关于vue状态过渡transition不起作用的原因解决
2019/04/09 Javascript
WebGL three.js学习笔记之阴影与实现物体的动画效果
2019/04/25 Javascript
详解关于表格合并span-method方法的补充(表格数据由后台动态返回)
2019/05/21 Javascript
element表格翻页第2页从1开始编号(后端从0开始分页)
2019/12/10 Javascript
Vue+elementUI实现多图片上传与回显功能(含回显后继续上传或删除)
2020/03/23 Javascript
Python编程之列表操作实例详解【创建、使用、更新、删除】
2017/07/22 Python
Python/Django后端使用PIL Image生成头像缩略图
2019/04/30 Python
基于Python的图像数据增强Data Augmentation解析
2019/08/13 Python
用Python将Excel数据导入到SQL Server的例子
2019/08/24 Python
澳大利亚巧克力花束和礼品网站:Tastebuds
2019/03/15 全球购物
公司业务员岗位职责
2014/03/18 职场文书
数学教育专业求职信
2014/07/22 职场文书
党旗在我心中演讲稿
2014/09/15 职场文书
2014财务部年度工作总结
2014/12/08 职场文书
2015年六一儿童节演讲稿
2015/03/19 职场文书
廉洁自律承诺书2016
2016/03/25 职场文书
2016年主题党日活动总结
2016/04/05 职场文书