来源: https://www.cnblogs.com/blackmatrix/p/5606364.html

静态方法是指类中无需实例参与即可调用的方法(不需要self参数),在调用过程中,无需将类实例化,直接在类之后使用.号运算符调用方法。

通常情况下,静态方法使用@staticmethod装饰器来声明。

示例代码:

class ClassA(object):

    @staticmethod
def func_a():
print('Hello Python') if __name__ == '__main__':
ClassA.func_a()
# 也可以使用实例调用,但是不会将实例作为参数传入静态方法
ca = ClassA()
ca.func_a()

这里需要注意的是,在Python 2 中,如果一个类的方法不需要self参数,必须声明为静态方法,即加上@staticmethod装饰器,从而不带实例调用它。

而在Python 3中,如果一个类的方法不需要self参数,不再需要声明为静态方法,但是这样的话只能通过类去调用这个方法,如果使用实例调用这个方法会引发异常。

class ClassA(object):

    def func_a():
print('Hello Python') if __name__ == '__main__':
ClassA.func_a()
# 以下使用实例调用会引发异常
ca = ClassA()
ca.func_a()

异常信息:

func_a() takes 0 positional arguments but 1 was given

因为func_a没有声明为静态方法,类实例在调用func_a时,会隐式地将self参数传入func_a,而func_a本身不接受任何参数,从而引发异常。

类方法在Python中使用比较少,类方法传入的第一个参数为cls,是类本身。并且,类方法可以通过类直接调用,或通过实例直接调用。但无论哪种调用方式,最左侧传入的参数一定是类本身。

通常情况下,类方法使用@classmethod装饰器来声明

class ClassA(object):

    @classmethod
def func_a(cls):
print(type(cls), cls) if __name__ == '__main__': ClassA.func_a() ca = ClassA()
ca.func_a()

从运行结果可以看出,无论是类调用还是实例调用,类方法都能正常工作。且通过打印cls,可以看出cls传入的都是类实例本身。

<class 'type'> <class '__main__.ClassA'>
<class 'type'> <class '__main__.ClassA'>

这里需要注意,如果存在类的继承,那类方法获取的类是类树上最底层的类。

class BaseA(object):

    @classmethod
def func_a(cls):
print(type(cls), cls) class BaseB(object):
pass class ClassA(BaseA, BaseB):
pass if __name__ == '__main__': ClassA.func_a() ca = ClassA()
ca.func_a()

代码中ClassA继承自BaseA、BaseB,在调用类方法时,虽然类方法是从BaseA继承而来,但是传入func_a的cls函数实际上是ClassA,也就是最底层(最具体)的类。

运行结果:

<class 'type'> <class '__main__.ClassA'>
<class 'type'> <class '__main__.ClassA'>

所以,在某些时候,需要明确调用类属性时,不要使用类方法传入的cls参数,因为它传入的是类树中最底层的类,不一定符合设计初衷。

可以直接通过类名访问类属性。

class BaseA(object):

    @classmethod
def func_a(cls):
     # 直接使用类名,而不使用cls
print(BaseA)
print(type(cls), cls) class BaseB(object):
pass class ClassA(BaseA, BaseB):
pass if __name__ == '__main__': ClassA.func_a()

实例方法,除静态方法与类方法外,类的其他方法都属于实例方法。

实例方法需要将类实例化后调用,如果使用类直接调用实例方法,需要显式地将实例作为参数传入。

最左侧传入的参数self,是实例本身。


def func_a(self):
print('Hello Python') if __name__ == '__main__':
# 使用实例调用实例方法
ca = ClassA()
ca.func_a()
# 如果使用类直接调用实例方法,需要显式地将实例作为参数传入
ClassA.func_a(ca)

Python类方法、静态方法与实例方法 -----类里面不需要实例化参数 和没带self的函数 调用此函数的方法的更多相关文章

  1. python 类方法 静态方法

    属性: 公有属性  (属于类,每个类一份) 普通属性  (属于对象,每个对象一份) 私有属性    (属于对象,跟普通属性相似,只是不能通过对象直接访问) 方法:(按作用) 构造方法 析构函数 方法: ...

  2. python学习之【第十七篇】:Python中的面向对象(类和对象)

    1.什么是类和类的对象? 类是一种数据结构,我们可以用它来定义对象,后者把数据值和行为特性融合在一起,类是现实世界的抽象的实体以编程形式出现.实例是这些对象的具体化.类是用来描述一类事物,类的对象指的 ...

  3. python之旅:元类

    type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello.py模块: class Hel ...

  4. 【转】python面向对象中的元类

    type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello.py模块: class Hel ...

  5. python ORM理解、元类

    元类 参考链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143191 ...

  6. python语法基础-函数-内置函数和匿名函数-长期维护

    ##################     内置函数        #######################  """ 一共是 68个内置函数: 反射相关的内置函 ...

  7. Python 中的map函数,filter函数,reduce函数

      自学python,很多地方都需要恶补.       三个函数比较类似,都是应用于序列的内置函数.常见的序列包括list.tuple.str.   1.map函数 map函数会根据提供的函数对指定序 ...

  8. Python类方法、静态方法与实例方法

    静态方法是指类中无需实例参与即可调用的方法(不需要self参数),在调用过程中,无需将类实例化,直接在类之后使用.号运算符调用方法. 通常情况下,静态方法使用@staticmethod装饰器来声明. ...

  9. python类方法以及类调用实例方法的理解

    classmethod类方法 1) 在python中.类方法 @classmethod 是一个函数修饰符,它表示接下来的是一个类方法,而对于平常我们见到的则叫做实例方法. 类方法的第一个参数cls,而 ...

随机推荐

  1. (1)什么是web框架和http协议

    Django是一个web框架 web框架的本质:就是一个socket服务端 bs架构本质上就是cs架构(cs架构就是client和server):bs架构就是browser和server,本质上bro ...

  2. [codeforces Mail.Ru Cup 2018 Round 1 D][ xor 操作]

    http://codeforces.com/contest/1054/problem/D 题目大意:一个序列a1 a2...an,可以对若干个元素进行取反,使所得的新序列异或和为0的区间个数最多. 题 ...

  3. 获奖感想和JAVA阶段性学习总结

    一.获奖感想 事实上,这次能够获得小黄衫,实在是出乎我的意料.毕竟班级中还有不少比我优秀的人,但我不会妄自菲薄.我知道,这件小黄衫不仅仅是老师对我的奖励,更是对我的一种鞭策,一种激励.它要求我要在以后 ...

  4. 直面Java 第002期

    . Java和C++同为面向对象语言,Java和C++主要区别有哪些?双方个有哪些优缺点? 解: C++ 被设计成主要用在系统性应用程序设计上的语言,对C语言进行了扩展.对于C语言这个为运行效率设计的 ...

  5. LG3978 【[TJOI2015]概率论】

    前置:卡特兰数 记\(C_n\)为\(n\)个节点的二叉树的个数,\(C_0=1\),对于\(n \geq 1\),取一个根节点,枚举其左子树大小,有 \[C_n=\sum_{i=0}^{n-1}C_ ...

  6. Redis源码剖析和注释(七)--- 快速列表(quicklist)

    Redis 快速列表(quicklist)1. 介绍quicklist结构是在redis 3.2版本中新加的数据结构,用在列表的底层实现. 通过列表键查看一下:redis 列表键命令详解 127.0. ...

  7. mysql修改用户密码

    修改自己的密码(root用户,其它用户应该也差不多) 方法一: [root@localhost /]# mysqladmin -u root -p password "root" ...

  8. C++编译器报错汇总

    1.error: ‘Person’ was not declared in this scope(1)若是一个类或函数的命名空间对使用者不可见(2)成员(静态)函数没有通过对象名或类名进行调用(3)虽 ...

  9. goreleaser 方便的go 二进制包分发工具

    goreleaser 可以帮助我们进行go 二进制包的快速,简单分发,我们可以用来创建一个github release 以及发布到homwbrew formula . 安装 mac 系统,实际根据自己 ...

  10. go-elasticsearch 来自官方的 golang es client

    elasticsearch 终于有了官方的golang sdk 了,地址 https://github.com/elastic/go-elasticsearch 当前还不稳定,同时主要是对于es7 的 ...