在python的类语法中,可以出现三种方法,具体如下:

  (1)实例方法

    1)第一个参数必须是实例本身,一般使用【self】表示。

    2)在实例方法中,可以通过【self】来操作实例属性,【类名】来操作类属性。

    3)实例方法只能通过实例对象去调用,尽管也可以通过类名间接调用【类名.方法名(self, ...)】,但此时仍然需要传入self对象。

  (2)类方法

    1)使用【@classmethod】修饰函数,且第一个参数必须是类本身,一般使用【cls】表示。

    2)在类方法中,可以使用【cls=类名】来操作类属性,但是不能操作实例属性(self对象中存储的变量)。

    3)类方法可以通过实例对象或者类对象调用。

  (3)静态方法

    1)使用【@staticmethod】修饰函数,不需要使用任何参数表示。与普通函数一样,只是将该方法放到了类中实现而已。

    2)使用方式与类方法一样,参考类方法中的 2)、3)。(注:静态方法只能通过【类名】去操作类属性;)

案例1:实例方法、类方法、静态方法使用

class Foo(object):
"""类三种方法语法形式"""
count = 0 # 统计实例对象的数量
class_method_count = 0 # 统计类方法的调用次数 # 实例方法
def __init__(self, name):
self.name = name
Foo.count += 1 # 实例方法
def instance_method(self):
print("是类{}的实例方法,只能被实例对象调用".format(Foo))
print("产生了一个<{}>实例,共有<{}>个实例对象".format(self.name, Foo.count)) # 类方法
@classmethod
def class_method(cls):
print("是类{}的类方法,可以被实例对象、类对象调用".format(cls))
cls.__static_method_test()
cls.class_method_count += 1 # 静态方法
@staticmethod
def static_method():
print("是类{}的静态方法,可以被实例对象、类对象调用".format(Foo))
print("+++以下内容为类方法class_method()的运行结果:")
Foo.class_method() @staticmethod
def __static_method_test():
print("调用了静态方法 static_method_test()") print("--"*20 + "实例方法测试" + "--"*20)
obj1 = Foo("dog")
obj1.instance_method() # <=> Foo.instance_method(obj1) print("--"*20 + "类方法测试" + "--"*20)
obj1.class_method()
print("--"*20)
Foo.class_method() print("--"*20 + "静态方法测试" + "--" * 20)
obj1.static_method()
print("--"*20)
Foo.static_method() """
运行结果:
----------------------------------------实例方法测试----------------------------------------
是类<class '__main__.Foo'>的实例方法,只能被实例对象调用
产生了一个<dog>实例,共有<1>个实例对象
----------------------------------------类方法测试----------------------------------------
是类<class '__main__.Foo'>的类方法,可以被实例对象、类对象调用
调用了静态方法 static_method_test()
----------------------------------------
是类<class '__main__.Foo'>的类方法,可以被实例对象、类对象调用
调用了静态方法 static_method_test()
----------------------------------------静态方法测试----------------------------------------
是类<class '__main__.Foo'>的静态方法,可以被实例对象、类对象调用
+++以下内容为类方法class_method()的运行结果:
是类<class '__main__.Foo'>的类方法,可以被实例对象、类对象调用
调用了静态方法 static_method_test()
----------------------------------------
是类<class '__main__.Foo'>的静态方法,可以被实例对象、类对象调用
+++以下内容为类方法class_method()的运行结果:
是类<class '__main__.Foo'>的类方法,可以被实例对象、类对象调用
调用了静态方法 static_method_test()
"""

  从案例1中得到,类方法与静态方法可以相互调用,但是静态方法只能用【类名】表示,而类方法用【cls】就比较方便了。

案例2:实例方法、类方法、静态方法在继承中(子类重写父类中的方法)的使用

class Foo(object):
X = 1
Y = 14 @staticmethod
def average(*mixes):
print("父类中的静态方法 average(*mixes)")
print("*****", mixes)
return sum(mixes) / len(mixes) @staticmethod
def static_method():
print("父类中的静态方法 static_method()")
return Foo.average(Foo.X, Foo.Y) # 注:因为这儿已经限定了只允许调用父类中的average() @classmethod
def class_method(cls): # 父类中的类方法
print("父类中的类方法 class_method(cls)")
return cls.average(cls.X, cls.Y) # 注:若用子类对象调用该函数,此时的cls==Son,故调用子类重写后的average() class Son(Foo):
@staticmethod
def average(*mixes): # "子类中重载了父类的静态方法"
print("子类中重载了父类的静态方法 average(*mixes)")
print("*****", mixes)
return sum(mixes) / len(mixes) print(Son.average(1, 2, 3), "\n" + "---" * 20)
print(Son.class_method(), "\n" + "---" * 20)
print(Son.static_method(), "\n" + "---" * 20) """
运行结果:
------------------------------------------------------------
子类中重载了父类的静态方法 average(*mixes)
***** (1, 2, 3)
2.0
------------------------------------------------------------
父类中的类方法 class_method(cls)
子类中重载了父类的静态方法 average(*mixes)
***** (1, 14)
7.5
------------------------------------------------------------
父类中的静态方法 static_method()
父类中的静态方法 average(*mixes)
***** (1, 14)
7.5
------------------------------------------------------------
"""

  从案例2中得到,子类对象调用父类中的 类方法 class_method(cls) 时,由于【cls】此时为【Son】,故会执行子类中的类方法、静态方法、静态属性;进一步推断出,类方法中【cls】取决于类方法的调用者,只有发生类方法调用后才能知道执行结果。而父类中静态方法 static_method()只能调用父类中类方法、静态方法、静态属性,与静态方法的调用者无关;进一步推断,静态方法可以提前预知程序的执行结果,如执行当前类中的某个类方法或静态方法。

  对案例2做一个多态测试,添加代码如下:

def test_polymorphic(foo):
"""
多态测试
:param foo: 父类对象
:return: None
"""
print(f.average(1, 2, 3)) f = Foo()
test_polymorphic(f) print("----"*10)
f = Son() # 会触发多态
test_polymorphic(f) """
父类中的静态方法 average(*mixes)
***** (1, 2, 3)
2.0
----------------------------------------
子类中重载了父类的静态方法 average(*mixes)
***** (1, 2, 3)
2.0
"""

  继续做多态测试,添加代码如下:

def test_polymorphic(foo):
"""
多态测试
:param foo: 父类对象
:return: None
"""
print(f.class_method()) f = Foo()
test_polymorphic(f) print("----"*10)
f = Son() # 会触发多态
test_polymorphic(f) """
父类中的类方法 class_method(cls)
父类中的静态方法 average(*mixes)
***** (1, 14)
7.5
----------------------------------------
父类中的类方法 class_method(cls)
子类中重载了父类的静态方法 average(*mixes)
***** (1, 14)
7.5
"""

案例3:使用类方法或静态方法初始化类(可以自定义类的初始方式)

class Book(object):
def __init__(self, title):
self.__title = title @classmethod
def object_create_by_class_method(cls, title_list):
"""
使用生产器实例化多个对象
:param title_list: 每个对象的初始化参数,List
:return:迭代器,每个实例化对象
"""
for title in title_list:
yield cls(title=title) @staticmethod
def object_create_by_static_method(title_list): # 功能与类方法一样
for title in title_list:
yield Book(title=title) @property
def title(self):
return self.__title @title.setter
def title(self, value):
if not isinstance(value, str):
raise TypeError('%s must be str' % value)
self.__title = value @title.deleter
def title(self):
del self.__title
# raise TypeError('Can not delete') books = ["Chinese", "mathematics", "English"]
g_books = Book.object_create_by_class_method(books)
print(g_books) # <generator object Book.object_create_by_class_method at 0x000001FB72AFEEC8> print(g_books.__next__().title) # 查看书的title -- Chinese
print(g_books.__next__().title) # 查看书的title -- mathematics book = g_books.__next__() # 得到一个实例化对象 print(book.title) # 查看书的title -- English
print(book.__dict__) # {'_Book__title': 'English'} book.title = "英语" # 修改属性
print(book.title) # 查看书的title -- 英语
print(book.__dict__) # {'_Book__title': '英语'} del book.title # 删除属性
print(book.__dict__) # {}

  从案例3中得到,使用类方法或者静态方法可以自定义类的初始化方式,本案例中实现的功能是使用生产器批量创建多个对象。同时,案列中使用了【property】属性,property的作用相当于执行了某个函数,并获得该函数的返回值;其使用方式有3种,分别为【@property --- get】、【@函数名.setter --- set】、【@函数名.deleter --- del】,后二种必须在第一种使用的情况下才能使用,在表现形式上就是通过实例化对象间接访问属性。

  最后,我们对案例3做微小改变,来看看实例方法、类方法、静态方法与类、对象之间的关系,代码如下:

class Book(object):
@classmethod
def object_create_by_class_method(cls):
pass @staticmethod
def object_create_by_static_method():
pass def instance_method(self):
pass book = Book()
print(book.instance_method) # 方法(绑定到对象:发生调用时,将【实例对象=self】自动作为第一个参数传入实例方法中)
print(book.object_create_by_class_method) # 方法(绑定到类:发生调用时,将【类=cls】自动作为第一个参数传入类方法中)
print(book.object_create_by_static_method) # 普通函数(非绑定:发生调用时,不需要传入任何参数,如self,cls) print(Book.instance_method) # 普通函数(非绑定,因为实例方法就存储在类的命名空间中)
print(Book.object_create_by_class_method) # 绑定到类
print(Book.object_create_by_static_method) # 普通函数(非绑定)
"""
<bound method Book.instance_method of <__main__.Book object at 0x000002481CEDE988>>
<bound method Book.object_create_by_class_method of <class '__main__.Book'>>
<function Book.object_create_by_static_method at 0x000002481D12C828> <function Book.instance_method at 0x000002481D12C8B8>
<bound method Book.object_create_by_class_method of <class '__main__.Book'>>
<function Book.object_create_by_static_method at 0x000002481D12C828>
"""

  可以发现,

    1)类中的实例方法都绑定了实例对象,故建议使用实例对象调用实例方法;

    2)类中的类方法都绑定了类,故建议使用类对象调用类方法,即使使用实例对象调用类方法,仍然自动将【类名】作为第一个参数传入类方法。

    3)而对于静态方法而言,无论使用实例对象或者类对象调用其方法都不会自动进行参数传递,故不做限制。

    4)若能用类解决的问题,就将类中的方法定义为类方法,这样可以避免实例化对象的开销。

绑定与非绑定的参考链接:

https://www.cnblogs.com/MrYang161/p/11431725.html

http://cda.pinggu.org/view/23514.html

python 类中方法总结 --- 实例方法、类方法、静态方法的更多相关文章

  1. python类中方法加单下划线、双下划线、前后双下滑线的区别

    首先看一段代码: class Foo(): def __init__(self): print "__init__ method" def public_method(self): ...

  2. Python 类中方法的内部变量,命名加'self.'变成 self.xxx 和不加直接 xxx 的区别

    先看两个类的方法: >>> class nc(): def __init__(self): self.name ='tester' #name变量加self >>> ...

  3. python类中方法__str__()和__repr__()简单粗暴总结

    在交互式模式下,类中同时实现__str__()和__repr__()方法: 直接输入实例名称显示repr返回的类容: 用print打印实例名称显示str返回的内容: >>> clas ...

  4. Python 简明教程 --- 20,Python 类中的属性与方法

    微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 与客户保持良好的关系可以使生产率加倍. -- Larry Bernstain 目录 类中的变量称为属 ...

  5. 第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法

    第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法 上节介绍了Python中类的静态方法,本节将结合案例详细说明相关内容. 一.    案例说明 本节定义了类Sta ...

  6. 第7.17节 Python类中的静态方法装饰器staticmethod 定义的静态方法深入剖析

    第7.17节  Python类中的静态方法装饰器staticmethod 定义的静态方法深入剖析 静态方法也是通过类定义的一种方法,一般将不需要访问类属性但是类需要具有的一些能力可以静态方法提供. 一 ...

  7. 第7.14节 Python类中的实例方法详析

    第7.14节 Python类中的实例方法详析 一.    实例方法的定义 在本章前面章节已经介绍了类的实例方法,实例方法的定义有三种方式: 1.    类体中定义实例方法 第一种方式很简单,就是在类体 ...

  8. 第8.12节 Python类中使用__dict__定义实例变量和方法

    上节介绍了使用实例的__dict__查看实例的自定义属性,其实还可以直接使用__dict__定义实例变量和实例方法. 一. 使用__dict__定义实例变量 语法: 对象名. dict[属性名] = ...

  9. 第8章 Python类中常用的特殊变量和方法目录

    第8章 Python类中常用的特殊变量和方法 第8.1节 Python类的构造方法__init__深入剖析:语法释义 第8.2节 Python类的__init__方法深入剖析:构造方法案例详解 第8. ...

随机推荐

  1. Java实现蓝桥杯 算法训练 ALGO-15 旅行家的预算

    问题描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离D1.汽车油箱的容量C(以升为单位).每升汽油能行驶的距离D2.出发点每升汽油价格P和沿 ...

  2. Java实现 LeetCode 757 设置交集大小至少为2(排序+滑动窗口)

    757. 设置交集大小至少为2 一个整数区间 [a, b] ( a < b ) 代表着从 a 到 b 的所有连续整数,包括 a 和 b. 给你一组整数区间intervals,请找到一个最小的集合 ...

  3. Java实现 蓝桥杯 算法训练 最大最小公倍数

    算法训练 最大最小公倍数 时间限制:1.0s 内存限制:256.0MB 问题描述 已知一个正整数N,问从1~N中任选出三个数,他们的最小公倍数最大可以为多少. 输入格式 输入一个正整数N. 输出格式 ...

  4. Java实现 蓝桥杯VIP 算法训练 学做菜

    算法训练 学做菜 时间限制:1.0s 内存限制:256.0MB 问题描述 涛涛立志要做新好青年,他最近在学做菜.由于技术还很生疏,他只会用鸡蛋,西红柿,鸡丁,辣酱这四种原料来做菜,我们给这四种原料标上 ...

  5. Java实现蓝桥杯七对数字

    今有7对数字:两个1,两个2,两个3,-两个7,把它们排成一行. 要求,两个1间有1个其它数字,两个2间有2个其它数字,以此类推,两个7之间有7个其它数字.如下就是一个符合要求的排列: 1712642 ...

  6. java实现第四届蓝桥杯连号区间数

    连号区间数 题目描述 小明这些天一直在思考这样一个奇怪而有趣的问题: 在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是: 如果区间[L, R] 里的所有元素(即此排列的第L个到第R ...

  7. 纯正中文版本pi-star系统下载

    基于3.4.17修改(稳定,发热量少) 不支持RPI 4 a/b+ 完美支持树莓派0,1,2,3 默认刷好卡,启动已经设置好所有参数(选好TFT屏幕,调制解调器类型GPIO,打开了DMR服务器(460 ...

  8. Linux中使用expect脚本实现远程机器自动登录_linux shell

    首先创建一个expect脚本ssh_expect,文件内容如下: #!/usr/bin/expect -f set hostname [lindex $argv 0] set user [lindex ...

  9. PHP上传进度支持(Upload progress in sessions)

    文件上传进度反馈, 这个需求在当前是越来越普遍, 比如大附件邮件. 在PHP5.4以前, 我们可以通过APC提供的功能来实现. 或者使用PECL扩展uploadprogress来实现. 从PHP的角度 ...

  10. C#数据结构与算法系列(一):介绍

    1.介绍 数据结构:是指相互之间存在一种或多种特定关系的数据元素的集合用计算机存储.组织数据的方式.数据结构分别为逻辑结构.(存储)物理结构和数据的运算三个部分. 数据结构包括:线性结构和非线性结构. ...