文章目录
1. 面向对象概述
在现实世界中存在各种不同形态的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象间的关系来描述事物之间的联系,这种思想就是面向对象。
面向对象技术概念:
- 类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
- 实例化:创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
2. 类和对象
类和对象的关系:
- 面向对象编程有两个非常重要的概念:类和对象。
- 对象是面向对象编程的核心。
- 具有相似特征和行为的事物的集合统称为类
- 对象是根据类创建的,一个类可以对应多个对象。
类的定义
类是由 3 部分组成的:
- 类的名称:首字母必须大写,比如 Person。
- 类的属性:用于描述事物的特征,比如性别。
- 类的方法:用于描述事物的行为,比如说话。
使用 class 关键字来声明一个类,基本格式如下:
class 类名:
类的属性
类的方法
根据类创建对象:
对象名 = 类名()
给对象添加属性:
对象名.新的属性名 = 值
示例:
class Person: #定义一个人类
role = 'person' #人的角色属性都是人
def walk(self): #人都可以走路,也就是有一个走路方法
print("person is walking...")
print(Person.role) #查看人的role属性
print(Person.walk) #引用人的走路方法,注意,这里不是在调用
# 结果
person
<function Person.walk at 0x000002715B7A7940>
#--------------------------------------------------------
class Employee:
'所有员工的基类'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print
"Total Employee %d" % Employee.empCount
def displayEmployee(self):
print
"Name : ", self.name, ", Salary: ", self.salary
// empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Employee.empCount 访问。
// 第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法。
// self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
#--------------------------------------------------------
class Student(object):
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def student_name(self):
return 'my name is {}'.format(self.name)
def student_name(self):
return 'my age is {}'.format(self.age)
def student_sex(self):
return 'i am a {}'.format(self.sex)
new_student = Student('jia', 12, 'boy')
print(new_student.student_name())
new1_student = Student('jia', 12, 'boy')
print(new1_student.student_name())
# 结果
my age is 12
my age is 12
3. 构造方法和析构方法
- 构造方法指的是
__init__
方法。- 当创建类的实例的时候,系统会自动调用构造方法,从而实现对类进行初始化的操作。
https://www.zhihu.com/question/46973549/answer/1842466508
class Car:
def __init__(self):
self.color = "黑色"
def toot(self):
print("%s的车在鸣笛..."%(self.color))
#----------------------------------------------
class Student():
def __init__(self, name, scores):
# 这里增加了属性name,并将所有成绩作为一个参数scores传入
# self.name是self的属性,单独的name是函数内的局部变量,参数也是局部变量
self.name = name
if len(scores) == 3:
self.scores = scores
else:
self.scores = [0] * 3
stu_1 = Student("Alice", [80, 90, 85])
print(stu_1.name)
print(stu_1.scores)
# 结果
Alice
[80, 90, 85]
- 当删除一个对象来释放类所占用资源的时候,Python 解释器默认会调用另外一个方法,这个方法就是
__del__( )
方法。__del__
方法被称为析构方法。
http://c.biancheng.net/view/2371.html
class CLanguage:
def __init__(self):
print("调用 __init__() 方法构造对象")
def __del__(self):
print("调用__del__() 销毁对象,释放其空间")
clangs = CLanguage()
#添加一个引用clangs对象的实例对象
cl = clangs
del clangs
print("***********")
# 结果
调用 __init__() 方法构造对象
***********
调用 __del__() 销毁对象,释放其空间
#---------------------------------------------
class CLanguage:
def __del__(self):
print("调用父类 __del__() 方法")
class cl(CLanguage):
def __del__(self):
print("调用子类 __del__() 方法")
c = cl()
del c
# 结果
调用子类 __del__() 方法
4. self 的使用
- 在方法的参数列表中,第 1 个参数永远都是 self。
- self 的字面意思是自己,我们可以把它当做 C++ 里面的 this 指针理解,表示的是对象自身。
- 当某个对象调用方法的时候,Python 解释器会把这个对象作为第 1 个参数传给 self,开发者只需要传递后面的参数就可以了。
- https://zhuanlan.zhihu.com/p/95788606
- http://c.biancheng.net/view/2266.html
class Dog:
def __init__(self, new_color):
self.color = new_color
def print_color(self):
print("颜色为:%s"%self.color)
dog_white = Dog("白色")
dog_white.print_color()
# 结果
颜色为:白色
#-------------------------------------
class Person:
def __init__(self):
print("正在执行构造方法")
# 定义一个study()实例方法
def study(self):
print(self,"正在学Python")
zhangsan = Person()
zhangsan.study()
lisi = Person()
lisi.study()
# 结果
正在执行构造方法
<__main__.Person object at 0x00000164781D7A60> 正在学Python
正在执行构造方法
<__main__.Person object at 0x0000016478219130> 正在学Python
#--------------------------------------
class Person:
def __init__(self):
print("正在执行构造方法")
# 定义一个study()实例方法
def study(self):
print(self,"正在学Python")
zhangsan = Person()
zhangsan.study()
lisi = Person()
lisi.study()
# 结果
zhangsan
lisi
5. 运算符重载
-
运算符重载是通过实现特定的方法使类的实例对象支持 Python 的各种内置操作 。例如: + 运算符是类里提供的
__add__
函数,当使用 + 进行加法运算的时候,实际上是调用了__add__
方法。
method | overload | call |
---|---|---|
__init__ | 构造函数 | 对象创建: X = Class(args) |
__del__ | 析构函数 | X对象收回 |
__add__ | 云算法+ | 如果没有_iadd_, X+Y, X+=Y |
__or__ | 运算符| | 如果没有_ior_,X|Y, X|=Y |
__repr__, __str__ | 打印,转换 | print(X),repr(X),str(X) |
__call__ | 函数调用 | X(*args, **kwargs) |
__getattr__ | 点号运算 | X.undefined |
__setattr__ | 属性赋值语句 | X.any=value |
__delattr__ | 属性删除 | del X.any |
__getattribute__ | 属性获取 | X.any |
__getitem__ | 索引运算 | X[key],X[i:j] |
__setitem__ | 索引赋值语句 | X[key],X[i:j]=sequence |
__delitem__ | 索引和分片删除 | del X[key],del X[i:j] |
__len__ | 长度 | len(X),如果没有__bool__,真值测试 |
__bool__ | 布尔测试 | bool(X) |
__lt__, __gt__, __le__, __ge__, __eq__, __ne__ | 特定的比较 | X<Y,X>Y,X<=Y,X>=Y, X==Y,X!=Y 注释:(lt: less than, gt: greater than, le: less equal, ge: greater equal, eq: equal, ne: not equal ) |
__radd__ | 右侧加法 | other+X |
__iadd__ | 实地(增强的)加法 | X+=Y(or else add) |
__iter__, __next__ | 迭代环境 | I=iter(X), next() |
__contains__ | 成员关系测试 | item in X(任何可迭代) |
__index__ | 整数值 | hex(X), bin(X), oct(X) |
__enter__, __exit__ | 环境管理器 | with obj as var: |
__get__, __set__, __delete__ | 描述符属性 | X.attr, X.attr=value, del X.attr |
__new__ | 创建 | 在__init__之前创建对象 |
常用重载运算符:
加法运算符重载
加法运算是通过调用 __add__ 方法完成重载的,当两个实例对象执行加法运算时,自动调用 __add__ 方法。
z = x + y
// 执行加法运算,实质是调用 __add__ 方法
索引和分片重载
跟索引相关的重载方法包括如下 3 个:
- __getitem__:索引、分片。
在对实例对象执行索引、分片或者 for 迭代操作时,会自动调用 __getitem__ 方法。
# 重写索引、分片运算符重载方法
def __getitem__(self, index):
return self.data[index]
- __setitem__:索引赋值。
通过赋值语句给索引或者分片赋值时,调用 __ setitem __ 方法实现对序列对象的修改。
def __setitem__(self, index, value):
self.data[index] = value
- __delitem__:索引和分片删除。
当使用 del 语句时,实质上会调用 __delitem__ 方法实现删除操作。
def __delitem__(self, index):
del self.data[index]
6. 封装
在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其含义是其他程序无法调用。要了解封装,离不开 “私有化”,就是将类或者是函数中的某些属性限制在某个区域之内,外部无法调用。
https://www.cnblogs.com/Michael–chen/p/6740455.html
https://www.jb51.net/article/146383.htm
https://www.cnblogs.com/ostrich-sunshine/p/9415698.html
封装数据的主要原因是:
保护隐私。(把不想别人知道的东西封装起来)。
封装方法的主要原因是:
隔离复杂度。(比如:电视机,我们看见的就是一个黑匣子,其实里面有很多电器元件,对于用户来说,我们不需要清楚里面都有些元件,电视机把那些电器元件封装在黑匣子里,提供给用户的只是几个按钮接口,通过按钮就能实现对电视机的操作。)
PS:在编程语言里,对外提供的接口(接口可理解为了一个入口),就是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
laowang = Person("老王", 30)
laowang.age = 300
print(laowang.age)
// 人的年龄可以随便设置,显然不可行。
为了保护类里面的属性,可以采用如下方式解决:
- 把属性定义为私有属性,即在属性名的前面加上两个下划线。
- 添加用于设置或获取属性值的两个方法供外界调用。
下面采用封装的方式,对 Person 类的代码进行修改:
def __init__(self, name, age):
self.name = name # 姓名
self.__age = age # 年龄
def set_age(self, new_age):
if new_age > 0 and new_age <= 120:
self.__age = new_age
def get_age(self):
return self.__age
其他示例:
# 类的设计者
class room: # 定义一个房间的类
def __init__(self,name,owner,length,width,high):
self.name = name
self.owner = owner
self.__length = length # 房间的长
self.__width = width # 房间的宽
self.__high = high # 房间的高
@property # @property 是 python 的一种装饰器,是用来修饰方法的
def area(self): # 求房间的平方的功能
return self.__length * self.__width # 对外提供的接口,隐藏了内部的实现细节
# 类的使用者(实例化对象通过接口,调用相关属性得到想要的值)
r1 = room("客厅","michael",20,30,9) # 实例化一个对象 r1
print(r1.area) # 通过接口使用 (area),使用者得到了客厅的面积
### 结果
600
###-----增加一个求体积功能-----###
# 扩展原有的代码,增加功能
# 类的设计者
class room: # 定义一个房间的类
def __init__(self,name,owner,length,width,high):
self.name = name # 房间名
self.owner = owner # 房子的主人
self.__length = length # 房间的长
self.__width = width # 房间的宽
self.__high = high # 房间的高
@property # @property 是 python 的一种装饰器,是用来修饰方法的
def area(self): # 对外提供的接口,隐藏内部实现
return self.__length * self.__width,\
self.__length * self.__width * self.__high # 增加了求体积功能
# 内部逻辑变了,只需增加这行代码就能简单实现,而且外部调用感知不到,仍然使用该方法,但是功能已经增加了
# 类的使用者
r1 = room("客厅","michael",20,30,9) # 实例化一个对象 r1
print(r1.area) # 通过接口使用 (area),使用者得到了客厅的面积
### 结果
(600, 5400)
7. 继承
概述
- 在现实生活中,继承一般指的是子女继承父辈的财产。在程序中,继承描述的是事物之间的从属关系。
- 类的继承是指在一个现有类的基础上构建一个新的类,构建出来的新类被称作子类,现有类被称作父类。
- 现实生活中,一个派生类往往会有多个基类。比如沙发床是沙发和床的功能的组合,这都是多重继承的体现。
- Python 支持多继承,多继承就是子类拥有多个父类,并且具有它们共同的特征,即子类继承了父类的方法和属性。
- 如果子类继承的多个父类间是平行的关系,子类先继承的哪个类就会调用哪个类的方法。
- 在继承关系中,子类会自动拥有父类定义的方法,但是有时子类想要按照自己的方式实现方法,即对父类中继承来的方法进行重写,使得子类中的方法覆盖掉跟父类同名的方法。需要注意的是,在子类中重写的方法要和父类被重写的方法具有相同的方法名和参数列表。
单继承:class 子类名(父类名)
多继承:class 子类名(父类名1,父类名2…)
https://www.cnblogs.com/bigberg/p/7182741.html
https://zhuanlan.zhihu.com/p/30239694
示例
单继承
class Father(object): # 定义一个父类
def fa(self): # 父类中的方法
print("这是父类的输出")
class Son(Father): # 定义一个子类,继承 Father 类
def so(selfs): # 在子类中定义其自身的方法
print("这是子类的输出")
c = Son()
c.fa() # 调用继承父类的 Person 类的方法
c.so() # 调用本身的方法
## 结果
这是父类的输出
这是子类的输出
多继承
class Item:
def info(self):
print("Item 父类中的方法")
class Product:
def info(self):
print("Product 父类中的方法")
class Computer(Item,Product):
pass
c = Computer()
c.info() # Item 父类中的方法
# 当以一个子类有多个直接父类时,该子类会继承得到所有父类的方法。
# 但是如果其中有多个父类包含同名方法会发生什么?
# 此时排在前面的父类中的方法会 "遮蔽" 后面父类中的方法。
#------------------------------------------------------------#
class Item:
def it(self):
print("Item 父类中的方法")
class Product:
def pr(self):
print("Product 父类中的方法")
class Computer(Item,Product):
def so(selfs):
print("这是子类的输出")
c = Computer()
c.it()
c.pr()
c.so()
# 结果
Item 父类中的方法
Product 父类中的方法
这是子类的输出
构造函数的继承
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
self.weight = 'weight'
def talk(self):
print("person is talking ......")
class Chinese(Person):
def __init__(self, name, age, language): # 先继承,再重构
Person.__init__(self, name, age) # 继承父类的构造方法,也可以写成:super(Chinese,self).__init__(name,age)
self.language = language # 定义类的本身属性
def walk(self):
print("chinese is walking ......")
class American(Person):
pass
c = Chinese('bigberg', 22, 'chinese')
# 如果我们只是简单的在子类 Chinese 中定义一个构造函数,其实就是在重构。
# 这样子类就不能继承父类的属性了。所以我们在定义子类的构造函数时,要先继承再构造,才获取父类的属性。
子类对父类方法的重写
# 如果我们对父类的方法需要修改,可以在子类中重构该方法。如下的 talk() 方法。
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
self.weight = 'weight'
def talk(self):
print("person is talking...")
class Chinese(Person):
def __init__(self, name, age, language):
Person.__init__(self, name, age)
self.language = language
print(self.name, self.age, self.weight, self.language)
def talk(self): # 子类重构方法
print('%s is speaking chinese' %self.name)
def walk(self):
print('chinese is walking...')
c = Chinese('bigberg', 22, 'Chinese')
c.talk()
# 结果
bigberg 22 weight Chinese
bigberg is speaking chinese
类继承的实例
class SchoolMember(object):
'''学习成员基类'''
member = 0
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
self.enroll()
def enroll(self):
'注册'
print('just enrolled a new school member [%s].' % self.name)
SchoolMember.member += 1
def tell(self):
print('----%s----' % self.name)
for k, v in self.__dict__.items():
print(k, v)
print('----end-----')
def __del__(self):
print('开除了[%s]' % self.name)
SchoolMember.member -= 1
class Teacher(SchoolMember):
'教师'
def __init__(self, name, age, sex, salary, course):
SchoolMember.__init__(self, name, age, sex)
self.salary = salary
self.course = course
def teaching(self):
print('Teacher [%s] is teaching [%s]' % (self.name, self.course))
class Student(SchoolMember):
'学生'
def __init__(self, name, age, sex, course, tuition):
SchoolMember.__init__(self, name, age, sex)
self.course = course
self.tuition = tuition
self.amount = 0
def pay_tuition(self, amount):
print('student [%s] has just paied [%s]' % (self.name, amount))
self.amount += amount
t1 = Teacher('Wusir', 28, 'M', 3000, 'python')
t1.tell()
s1 = Student('haitao', 38, 'M', 'python', 30000)
s1.tell()
s2 = Student('lichuang', 12, 'M', 'python', 11000)
print(SchoolMember.member)
del s2
print(SchoolMember.member)
8. 多态
在强类型语言(例如 Java 或 C#)中,多态指允许使用一个父类类型的变量或常量来引用一个子类类型的对象。Python 中多态指在不考虑对象类型的情况下使用对象。
https://www.cnblogs.com/feeland/p/4419121.html
相比于强类型,Python 更推崇 “鸭子类型”。“鸭子类型” 是这样推断的:如果一只生物走起路来像鸭子,游起泳来像鸭子,叫起来也像鸭子,那么它就可以被当做鸭子。也就是说,它不关注对象的类型,而是关注对象具有的行为。
示例一
class A(object):
def test(self):
print("A--test")
class B(A):
def test(self):
print("B--test")
def func(temp):
temp.test()
a = A()
b = B()
func(a)
func(b)
# 结果
A--test
B--test
// 对象 a、b 分别调用 func 函数的结果不一样,这体现了多态。
示例二
class Person(object):
def __init__(self,name,sex):
self.name = name
self.sex = sex
def print_title(self):
if self.sex == "male":
print("man")
elif self.sex == "female":
print("woman")
class Child(Person): # Child 继承 Person
def print_title(self):
if self.sex == "male":
print("boy")
elif self.sex == "female":
print("girl")
May = Child("May","female")
Peter = Person("Peter","male")
print(May.name,May.sex,Peter.name,Peter.sex)
May.print_title()
Peter.print_title()
- 当子类和父类都存在相同的 print_title()方法时,子类的 print_title() 覆盖了父类的 print_title(),在代码运行时,会调用子类的 print_title()。这样,我们就获得了继承的另一个好处:多态。
- 多态的好处就是,当我们需要传入更多的子类,例如新增 Teenagers、Grownups 等时,我们只需要继承 Person 类型就可以了,而 print_title() 方法既可以直不重写(即使用 Person 的),也可以重写一个特有的。这就是多态的意思。调用方只管调用,不管细节,而当我们新增一种 Person 的子类时,只要确保新方法编写正确,而不用管原来的代码。这就是著名的 开闭 原则:
- 对扩展开放(Open for extension):允许子类重写方法函数
- 对修改封闭(Closed for modification):不重写,直接继承父类方法函数
9. 类属性和实例属性
- 属性就是属于一个对象的数据或者函数,我们可以通过句点
.
来访问属性,同时 python 还支持在运作中添加和修改属性。 - 数据变量类似于
name = 'scolia'
这样的形式会称其为字段。而类里面的函数又称为方法。而方法又分为实例方法
,类方法
和静态方法
。 类属性
:就是类对象所拥有的属性,它被所有类对象的实例对象所共有,类对象和实例对象可以访问。实例属性
:实例对象所拥有的属性,只能通过实例对象访问。
https://blog.csdn.net/qq_39457296/article/details/108000982
https://www.jb51.net/article/226154.htm
示例一
class Student:
name='黎明' #属于类属性 就是 Student 类对象所拥有的
def __init__(self,age):
self.age=age #实例属性
pass
pass
lm=Student(17)
print(lm.name) #通过实例对象去访问类属性
print(lm.age)
## 结果
黎明
17
示例二
class Student:
name='黎明' #属于类属性 就是 Student 类对象所拥有的
def __init__(self,age):
self.age=age #实例属性
pass
pass
lm=Student(17)
print(lm.name) #通过实例对象访问类属性
print(Student.name) #通过类对象访问类属性
## 结果
黎明
黎明
示例三:对类属性进行修改
class Student:
name='黎明' #属于类属性,就是 Student 类对象所拥有的
def __init__(self,age):
self.age=age #实例属性
pass
pass
Student.name='赵丽颖' #类属性此时已被修改
lm=Student(17)
print(lm.name) #通过实例对象去访问类属性
lm.name='李嘉欣' #通过实例对象对类属性进行修改,不可以,并未被修改
print(lm.name) #追加新的属性,对于下方调用仍未修改
print(lm.age)
print('------小花的数据---------')
xh=Student(28)
print(xh.name) #name 还是黎明
print(xh.age)
print('-------------通过类对象访问 name-------------')
print(Student.name)
## 结果
赵丽颖
李嘉欣
17
------小花的数据---------
赵丽颖
28
-------------通过类对象访问 name-------------
赵丽颖
10. 实例方法(instance method),类方法(class method)与静态方法(static method)
https://blog.csdn.net/lihao21/article/details/79762681
https://www.cnblogs.com/yunxiaofei/p/11210240.html
10.1 实例方法
- Python 的实例方法用得最多,也最常见。
class Kls(object):
def __init__(self, data):
self.data = data
def printd(self):
print(self.data)
ik1 = Kls('leo')
ik2 = Kls('lee')
ik1.printd()
ik2.printd()
## 结果
leo
lee
printd
为一个实例方法。实例方法第一个参数为 self
,当使用 ik1.printd()
调用实例方法时,实例 ik1
会传递给 self
参数,这样 self
参数就可以引用当前正在调用实例方法的实例。利用实例方法的这个特性,上述代码正确输出了两个实例的成员数据。
10.2 类方法
- Python 的类方法采用装饰器
@classmethod
来定义。
class Kls(object):
num_inst = 0
def __init__(self):
Kls.num_inst = Kls.num_inst + 1
@classmethod
def get_no_of_instance(cls):
return cls.num_inst
ik1 = Kls()
ik2 = Kls()
print(ik1.get_no_of_instance())
print(Kls.get_no_of_instance())
## 结果
2
2
在上述例子中,我们需要统计类 Kls
实例的个数,因此定义了一个类变量 num_inst
来存放实例个数。通过装饰器 @classmethod
的使用,方法 get_no_of_instance
被定义成一个类方法。在调用类方法时,Python 会将类 class Kls
传递给 cls
,这样在 get_no_of_instance
内部就可以引用类变量 num_inst
。由于在调用类方法时,只需要将类型本身传递给类方法,因此既可以通过类也可以通过实例来调用类方法。
10.3 静态方法
- 在开发中,我们常常需要定义一些方法,这些方法跟类有关,但在实现时并不需要引用类或者实例。例如:设置环境变量,修改另一个类的变量等。这个时候,我们可以使用静态方法。
- Python 使用装饰器
@staticmethod
来定义一个静态方法。
IND = 'ON'
class Kls(object):
def __init__(self, data):
self.data = data
@staticmethod
def checkind():
return IND == 'ON'
def do_reset(self):
if self.checkind():
print('Reset done for: %s' % self.data)
def set_db(self):
if self.checkind():
print('DB connection made for: %s' % self.data)
ik1 = Kls(24)
ik1.do_reset()
ik1.set_db()
## 结果
Reset done for: 24
DB connection made for: 24
在代码中,我们定义了一个全局变量 IND
,由于 IND
跟类 Kls
相关,所以我们将方法 checkind
放置在类 Kls
中定义。方法 checkind
只需检查 IND
的值,而不需要引用类或者实例,因此,我们将方法 checkind
定义为静态方法。对于静态方法,Python 并不需要传递类或者实例,因此,既可以使用类也可以使用实例来调用静态方法。
10.4 实例方法,类方法与静态方法的区别
注意下述代码中方法 foo,class_foo,static_foo
的定义以及使用。
class Kls(object):
def foo(self, x):
print('executing foo(%s,%s)' % (self, x))
@classmethod
def class_foo(cls,x):
print('executing class_foo(%s,%s)' % (cls,x))
@staticmethod
def static_foo(x):
print('executing static_foo(%s)' % x)
ik = Kls()
# 实例方法
ik.foo(1)
print(ik.foo)
print('==========================================')
# 类方法
ik.class_foo(1)
Kls.class_foo(1)
print(ik.class_foo)
print('==========================================')
# 静态方法
ik.static_foo(1)
Kls.static_foo('hi')
print(ik.static_foo)
结果
executing foo(<__main__.Kls object at 0x0000022663377610>,1)
<bound method Kls.foo of <__main__.Kls object at 0x0000022663377610>>
==========================================
executing class_foo(<class '__main__.Kls'>,1)
executing class_foo(<class '__main__.Kls'>,1)
<bound method Kls.class_foo of <class '__main__.Kls'>>
==========================================
executing static_foo(1)
executing static_foo(hi)
<function Kls.static_foo at 0x00000226633B7CA0>