[887]python中@classmethod和@staticmethod
一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。 而使用@staticmethod或@classmethod,就可以不需要实例化,**直接类名.方法名()**来调用。 这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁。
既然@staticmethod和@classmethod都可以**直接类名.方法名()**来调用,那他们有什么区别呢 ?
从它们的使用上来看,
- @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
- @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
- 如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。
- 而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。
Python中3种方式定义类方法, 常规方式, @classmethod修饰方式, @staticmethod修饰方式.
class A(object):
def foo(self, x):
print("executing foo(%s,%s)" % (self, x))
print('self:', self)
@classmethod
def class_foo(cls, x):
print("executing class_foo(%s,%s)" % (cls, x))
print('cls:', cls)
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % x)
a = A()
1.定义方式
普通的类方法foo()需要通过self参数隐式的传递当前类对象的实例。 @classmethod修饰的方法class_foo()需要通过cls参数传递当前类对象。@staticmethod修饰的方法定义与普通函数是一样的。
self和cls的区别不是强制的,只是PEP8中一种编程风格,slef通常用作实例方法的第一参数,cls通常用作类方法的第一参数。即通常用self来传递当前类对象的实例,cls传递当前类对象。
问题:@staticmethod修饰的方法函数与普通的类外函数一样,为什么不直接使用普通函数? @staticmethod是把函数嵌入到类中的一种方式,函数就属于类,同时表明函数不需要访问这个类。通过子类的继承覆盖,能更好的组织代码。
2.绑定对象
foo方法绑定对象A的实例,class_foo方法绑定对象A,static_foo没有参数绑定。
>>> print(a.foo)
<bound method A.foo of <__main__.A object at 0x0278B170>>
>>> print(a.class_foo)
<bound method A.class_foo of <class '__main__.A'>>
>>> print(a.static_foo)
<function A.static_foo at 0x02780390>
3.调用方式
foo可通过实例a调用,类对像A直接调用会参数错误。
>>> a.foo(1)
executing foo(<__main__.A object at 0x0278B170>,1)
self: <__main__.A object at 0x0278B170>
>>> A.foo(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'x'
但foo如下方式可以使用正常,显式的传递实例参数a。
>>> A.foo(a, 1)
executing foo(<__main__.A object at 0x0278B170>,1)
self: <__main__.A object at 0x0278B170>
class_foo通过类对象或对象实例调用。
>>> A.class_foo(1)
executing class_foo(<class '__main__.A'>,1)
cls: <class '__main__.A'>
>>> a.class_foo(1)
executing class_foo(<class '__main__.A'>,1)
cls: <class '__main__.A'>
static_foo通过类对象或对象实例调用。
>>> A.static_foo(1)
executing static_foo(1)
>>> a.static_foo(1)
executing static_foo(1)
4.继承与覆盖普通类函数是一样的。
class B(A):
pass
b = B()
b.foo(1)
b.class_foo(1)
b.static_foo(1)
# executing foo(<__main__.B object at 0x007027D0>,1)
# self: <__main__.B object at 0x007027D0>
# executing class_foo(<class '__main__.B'>,1)
# cls: <class '__main__.B'>
# executing static_foo(1)
5. 其它
class A(object):
# 属性默认为类属性(可以给直接被类本身调用)
num = "类属性"
# 实例化方法(必须实例化类之后才能被调用)
def func1(self): # self : 表示实例化类后的地址id
print("func1")
print(self)
# 类方法(不需要实例化类就可以被类本身调用)
@classmethod
def func2(cls): # cls : 表示没用被实例化的类本身
print("func2")
print(cls)
print(cls.num)
cls().func1()
# 不传递传递默认self参数的方法(该方法也是可以直接被类调用的,但是这样做不标准)
def func3():
print("func3")
print(A.num) # 属性是可以直接用类本身调用的
# A.func1() 这样调用是会报错:因为func1()调用时需要默认传递实例化类后的地址id参数,如果不实例化类是无法调用的
A.func2()
A.func3()
参考:https://www.cnblogs.com/elie/p/5876210.html https://blog.csdn.net/polyhedronx/article/details/81911548 https://www.runoob.com/python/python-func-classmethod.html
- Mac OSX网络诊断命令
- spring cloud 学习(5) - config server
- Java魔法堂:解读基于Type Erasure的泛型
- spring cloud 学习(3) - feign入门
- Java集合源码分析(四)HashMap
- Java魔法堂:解读基于Type Erasure的泛型
- 显示mybatis的执行的sql
- spring cloud 学习(2) - eureka server注册中心高可用及安全认证
- mybatis在xml文件中处理大于号小于号的方法
- kafka集群部署
- Hadoop(九)Hadoop IO之Compression和Codecs
- 安卓第二夜 有趣的架构
- spring-boot 速成(12) - 如何注入多个redis StringRedisTemplate
- Hadoop(八)Java程序访问HDFS集群中数据块与查看文件系统
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 发布更新|腾讯云 Serverless 产品动态 20200723
- Spring中异步注解@Async的使用、原理及使用时可能导致的问题
- Elasticsearch 聚合数据结果不精确,怎么破?
- Elasticsearch 预处理没有奇技淫巧,请先用好这一招!
- 时滞微分方程的matlab解法
- Zabbix Monitoring Logstash
- Join()和 List()的 6 种化学反应
- lettuce和hbase中对netty的使用你都了解吗?
- SAS-新规试行下诞生的程序
- AIOHTTP的实战(一)
- JMeter二次开发插件实例
- 「R」Obtain RNAseq Values for a Specific Gene in Xena Database
- 使用JMeter测试TCP协议
- SQL使用(一):如何使用SQL语句去查询第二高的值
- OpenCV加载图片显示对应类型(位深度)方法