技术背景

在Python的类型设计中,有时候会遇到一个cls参数。其实cls参数就是一个约定俗成的名称,用其他的名字也能正常运行但不建议这么用。它的作用类似于实例方法中的self参数,代表的是类本身,可以用于访问类的参数和类的方法。本文通过一些具体示例,来演示cls参数的功能和用法。

简单类实现

首先我们用普通的方法做一个最基本的测试案例:

class Test:
def __init__(self):
self.prefix = "Hello\t" def excute(self, x):
print (self.prefix+x) t = Test()
x = "Bob"
t.excute(x)
x = "Alice"
t.excute(x)

这里Test类型的操作逻辑是,在初始化函数中初始化一个prefix变量,然后在excute中调用打印函数,打印prefix变量和一个外部输入变量的整合字符串,执行效果如下:

Hello   Bob
Hello Alice

这个方法的一个局限性在于,类Test中的函数,如excute函数,必须要新建一个实例t之后,才能够调用到它的excute方法。如果跳过初始化的步骤直接调用excute方法:

class Test:
def __init__(self):
self.prefix = "Hello\t" def excute(self, x):
print (self.prefix+x) Test.excute()

运行结果会告诉你,这需要两个变量的输入才能够正常的运行:

Traceback (most recent call last):
File "/home/test_cls.py", line 8, in <module>
Test.excute()
TypeError: Test.excute() missing 2 required positional arguments: 'self' and 'x'

例如,我们先初始化一个t实例,但是方法调用我们不调用t中的excute函数,而是直接调用Test类中的函数:

class Test:
def __init__(self):
self.prefix = "Hello\t" def excute(self, x):
print (self.prefix+x) t = Test()
x = "Bob"
Test.excute(t, x)

这样也是可以正常运行的:

Hello   Bob

classmethod方法

通过classmethod方法,可以允许我们不需要在外部对类初始化,而直接访问到类的内部属性、参数和函数。也就是对于classmethod装饰的函数,约定使用cls变量作为开头。

class Test:
prefix = "Hello\t"
@classmethod
def excute(cls, x):
print (cls.prefix+x) x = "Bob"
Test.excute(x)

这样就可以直接在外部调用到类的内部函数:

Hello   Bob

当然,前面提到过,这里即使换一个变量名,也是可以正常运行的:

class Test:
prefix = "Hello\t"
@classmethod
def excute(self, x):
print (self.prefix+x) x = "Bob"
Test.excute(x)

因为第一个参数代表的是类本身,因此可以执行成功:

Hello   Bob

这里需要说明的是,classmethod装饰器的作用,就是把函数的第一个参数相关的内容给省去了,如果不使用classmethod进行装饰,例如:

class Test:
prefix = "Hello\t"
def excute(cls, x):
print (cls.prefix+x) x = "Bob"
Test.excute(x)

这样运行会报错:

Traceback (most recent call last):
File "/home/test_cls.py", line 7, in <module>
Test.excute(x)
TypeError: Test.excute() missing 1 required positional argument: 'x'

提示的内容是参数缺失,其实也就是少了一个初始化的步骤。那么有一种情况是,类似于prefix这种的类属性是在__init__函数中定义的,这是比较常见的情况。在这种情况下,如果不初始化一个实例,就无法访问到初始化参数。但是前面也提到了,cls就代表类本身,那么自然可以通过cls来访问类中的函数,包括初始化的函数:

class Test:
def __init__(self):
self.prefix = "Hello\t" @classmethod
def excute(cls, x):
cls.__init__(cls)
print (cls.prefix+x) x = "Bob"
Test.excute(x)

这个代码可以被正确执行:

Hello   Bob

同时,通过classmethod,可以修改类的属性:

class Test:
prefix = "Hello\t"
@classmethod
def excute(cls, x):
print (cls.prefix+x)
cls.prefix = cls.prefix+x+"\t" x = "Bob"
Test.excute(x)
x = "Alice"
Test.excute(x)

这里在excute函数中,每次打印之后,都会修改一下prefix参数,所以打印输出结果如下:

Hello   Bob
Hello Bob Alice

当然,修改属性这样的操作,在普通的类实现中也是可以操作的:

class Test:
def __init__(self):
self.prefix = "Hello\t" def excute(self, x):
print (self.prefix+x)
self.prefix = self.prefix+x+"\t" t = Test()
x = "Bob"
t.excute(x)
x = "Alice"
t.excute(x)

用self得到的结果是一样的:

Hello   Bob
Hello Bob Alice

如果不使用classmethod,也可以通过staticmethod来实现一个类似功能:

class Test:
def __init__(self):
self.prefix = "Hello\t"
@staticmethod
def excute(self, x):
print (self.prefix+x)
self.prefix = self.prefix+x+"\t" t = Test()
x = "Bob"
Test.excute(t, x)
x = "Alice"
Test.excute(t, x)

但是staticmethod不对参数进行初始化,虽然可以在外部直接调用类函数,但是需要手动初始化一个实例。输出结果是一致的:

Hello   Bob
Hello Bob Alice

总结概要

本文介绍了在Python的classmethod装饰的类方法的cls变量的意义,通过几个不同的示例对比,凸显cls变量在Python编程中的应用场景。对于大多数的场景来说,使用普通的Python类和函数定义即可。如果需要在类的外部使用类的内部函数,但是可能有多个不同初始化的类输入,那么可以使用staticmethod进行装饰。如果只有一个类,而有多种不同的输入场景下,可以使用classmethod进行装饰。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/cls.html

作者ID:DechinPhy

更多原著文章:https://www.cnblogs.com/dechinphy/

请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

Python中的cls变量的更多相关文章

  1. python中self cls init的理解

    原创文章,未经允许禁止转载! python中self cls init的理解 python中self cls init的理解

  2. python中的cls到底指的是什么

    python中的cls到底指的是什么,与self有什么区别? 2018年07月31日 11:13:09 rs勿忘初心 阅读数:7769   作者:秦风链接:https://www.zhihu.com/ ...

  3. Python中什么是变量Python中定义字符串

    在Python中,变量的概念基本上和初中代数的方程变量是一致的. 例如,对于方程式 y=x*x ,x就是变量.当x=2时,计算结果是,当x=5时,计算结果是25. 只是在计算机程序中,变量不仅可以是数 ...

  4. Python中的高级变量类型

    高级变量类型 目标 列表 元组 字典 字符串 公共方法 变量高级 知识点回顾 Python 中数据类型可以分为 数字型 和 非数字型 数字型 整型 (int) 浮点型(float) 布尔型(bool) ...

  5. python中的私有变量

    class Test1: def f1(self): self.name ="张三" self.__age = 20 #使用名称变形实现私有变量 print(self.name) ...

  6. Python中什么是变量

    在Python中,变量的概念基本上和初中代数的方程变量是一致的. 例如,对于方程式 y=x*x ,x就是变量.当x=2时,计算结果是4,当x=5时,计算结果是25. 只是在计算机程序中,变量不仅可以是 ...

  7. 【python】【转】python中isinstance判断变量类型用法

    来源 http://www.jb51.net/article/15696.htm 在Python中只需要使用内置的函数isinstance,使用起来非常简单,比如下面的例子: 复制代码 代码如下: c ...

  8. python中添加环境变量

    import sys sys.path 系统环境是一个list,可以将自己需要的库添加进入,例如mysql库,hive库等等.有三种方式添加,均验证通过:     1 临时添加,在一个shell窗口中 ...

  9. python中enumerate、变量类型转换

    enumerate可以在遍历过程中自动生成新的一列并从0开始计数 1 a = ["hello", "world", "dlrb"] 2 fo ...

  10. Python中关于__main__变量的问题

    在Python代码的编写中,经常会用到这么一句: if __name__ == "__main__": .... 这句代码之前的语句在整个模块被其他文件调用的时候会被运行,而这句代 ...

随机推荐

  1. go 结构体根据某个字段进行排序

    前言 在任何编程语言中,关乎到数据的排序都会有对应的策略,我们来看下 Golang 是怎样对数据进行排序,以及我们如何优化处理使用 go 排序 go 可以针对任何对象排序,虽然很多情况下是一个 sli ...

  2. MFC编程中与编码方式有关的宏定义的使用

    1 多字节字符集:char *strcpy(char *strDestination, const char *strSource); Unicode字符集:wchar_t *wcscpy(wchar ...

  3. 插入排序(LOW)

    博客地址:https://www.cnblogs.com/zylyehuo/ # _*_coding:utf-8_*_ def insert_sort(li): for i in range(1, l ...

  4. Docker镜像介绍

    一.Docker镜像介绍 镜像是Docker的三大核心概念之一. Docker运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker会尝试先从默认的镜像仓库下载(默认使用Docker Hu ...

  5. SQL Server 中的异常处理

    为什么我们需要 SQL Server 中的异常处理? 让我们通过一个示例来了解 SQL Server 中异常处理的必要性.因此,创建一个 SQL Server 存储过程,通过执行以下查询来除以两个数字 ...

  6. MySQL-事务中的一致性读和锁定读的具体原理

    前言 上一篇文章MySQL-InnoDB行锁中,提到过一致性锁定读和一致性非锁定读,这篇文章会详细分析一下在事务中时,具体是如何实现一致性的. 一致性读原理 start transaction和beg ...

  7. 再说PG的连接

    前面说过连接PG的方法,但是遇到问题又不通了. 按照前面的做法还是不行,正是鼻子气歪了. 到pg老家下载PGODBC,安装了,还是不行. 其实仅仅copy一个libpg.dll是不够的.因为libpg ...

  8. FireDAC 下FDMEMTable的的字段自动获取

    用clientdataset可以在设计时获取表结构.带来了不少方便.那么在FireDAC下如何处理? TSQLConnect继续provider的方法是没有问题的.而FireDAC不支持Provide ...

  9. PMP学习记录

    本人在2020年12月已经顺利拿到PMP证书. 第一次听说PMP证书是2016年,一个同事说考试通过拿到了PMP证书,当时对PMP不是很了解.也未作深入了解,当时认为俺是做技术的,这个证书没啥用.O( ...

  10. RAGflow搭建text-to-sql的AI研发助手

    一.概述 text-to-sql 技术允许用户通过自然语言提问,系统自动将其转换为 SQL 语句并执行,大大降低了数据查询的门槛,提高了工作效率. text-to-sql 技术在数据分析.智能客服.数 ...