深入了解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 相关文章推荐
在IIS服务器上以CGI方式运行Python脚本的教程
Apr 25 Python
Python中用于转换字母为小写的lower()方法使用简介
May 19 Python
Django中使用group_by的方法
May 26 Python
python 循环遍历字典元素的简单方法
Sep 11 Python
Python实现的json文件读取及中文乱码显示问题解决方法
Aug 06 Python
Django xadmin开启搜索功能的实现
Nov 15 Python
解决Tensorflow 使用时cpu编译不支持警告的问题
Feb 03 Python
使用Tensorflow-GPU禁用GPU设置(CPU与GPU速度对比)
Jun 30 Python
使用python实现下载我们想听的歌曲,速度超快
Jul 09 Python
Python爬虫使用bs4方法实现数据解析
Aug 25 Python
K近邻法(KNN)相关知识总结以及如何用python实现
Jan 28 Python
Django drf请求模块源码解析
Jun 08 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
PHP3 safe_mode 失效漏洞
2006/10/09 PHP
探讨多键值cookie(php中cookie存取数组)的详解
2013/06/06 PHP
php魔术函数__call()用法实例分析
2015/02/13 PHP
PHP操作MySQL的mysql_fetch_* 函数的常见用法教程
2015/12/25 PHP
thinkPHP数据库增删改查操作方法实例详解
2016/12/06 PHP
Laravel 5.4.36中session没有保存成功问题的解决
2018/02/19 PHP
php多进程中的阻塞与非阻塞操作实例分析
2020/03/04 PHP
你必须知道的Javascript知识点之"字面量和对应类型"说明介绍
2013/04/23 Javascript
js的隐含参数(arguments,callee,caller)使用方法
2014/01/28 Javascript
js单词形式的运算符
2014/05/06 Javascript
js浏览器本地存储store.js介绍及应用
2014/05/13 Javascript
node+express+jade制作简单网站指南
2014/11/26 Javascript
在JavaScript的AngularJS库中进行单元测试的方法
2015/06/23 Javascript
浅谈jQuery的offset()方法及示例分享
2015/07/17 Javascript
AngularJs bootstrap搭载前台框架——准备工作
2016/09/01 Javascript
node.js+captchapng+jsonwebtoken实现登录验证示例
2017/08/17 Javascript
jQuery ajax调用webservice注意事项
2017/10/08 jQuery
JavaScript事件对象event用法分析
2018/07/27 Javascript
Vue 权限控制的两种方法(路由验证)
2019/08/16 Javascript
vue控制多行文字展开收起的实现示例
2019/10/11 Javascript
通过实例解析vuejs如何实现调试代码
2020/07/16 Javascript
python实现探测socket和web服务示例
2014/03/28 Python
python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)
2014/06/09 Python
使用Python脚本来控制Windows Azure的简单教程
2015/04/16 Python
Python基于Tkinter实现的记事本实例
2015/06/17 Python
基于python的Tkinter实现一个简易计算器
2015/12/31 Python
python的dataframe和matrix的互换方法
2018/04/11 Python
mac下如何将python2.7改为python3
2018/07/13 Python
Python 仅获取响应头, 不获取实体的实例
2019/08/21 Python
Python3和pyqt5实现控件数据动态显示方式
2019/12/13 Python
解决Keras中Embedding层masking与Concatenate层不可调和的问题
2020/06/18 Python
安装并免费使用Pycharm专业版(学生/教师)
2020/09/24 Python
Python创建简单的神经网络实例讲解
2021/01/04 Python
Python爬虫后获取重定向url的两种方法
2021/01/19 Python
css3通过scale()、rotate()实现放大、旋转
2020/03/19 HTML / CSS
HTML利用九宫格原理进行网页布局
2020/03/13 HTML / CSS