十五、类函数、成员函数、静态函数、抽象函数、方法伪装属性
本篇博客是滚雪球学 Python 第二轮的最后一篇博客,我们将内容继续提升到面向对象部分,为你补充类里面的一些装饰器,学习之后,希望你的 Python 基础知识可以更上一层楼。
15.1 类函数 @classmethod
先直接看代码,再对代码内容进行分析与学习。
class My_Class(object):# 在类定义中定义变量
cls_var = "类变量"def __init__(self):
print("构造函数")
self.x = "构造函数中的属于实例变量"# 类方法,第一个参数必须默认传类,一般习惯用 cls。
@classmethod
def class_method(cls):
print("class_method 是类方法,类名直接调用")
# 类方法不可以调用类内部的对象变量(实例变量)
# print(cls.x)# 类方法可以通过类名直接调用,也可以通过对象来调用
# 即使通过实例调用类方法,Python 自动传递的也是类,而不是实例
My_Class.class_method()
my_class_dom = My_Class()
# 通过类的对象调用
my_class_dom.class_method()
首先要掌握的是类函数的定义格式,在普通函数的前面添加装饰器
@classmethod
,该函数就会转换为类函数,同时函数的第一个参数默认是 cls
,该变量名可以任意,建议使用成 cls
,这个是程序员之间的约定。 @classmethod
def class_method(cls):
同时类函数在调用的时候,可以通过
类名.
的形式进行调用,也可以通过 对象.
的形式调用,不过这两种调用都只是将类传递到了函数内部,不存在差异。 类函数不能调用实例变量,只能调用类变量,所谓类变量就是在类中独立声明,不在任何函数中出现的变量。在上述代码中,类变量声明部分代码如下:
class My_Class(object):
# 在类定义中定义变量
cls_var = "类变量"
在 Python 中,大部分
@classmethod
装饰的函数末尾都是 return cls(XXX)
, return XXX.__new__ ()
也就是 @classmethod
的一个主要用途是作为构造函数。15.2 静态函数 @staticmethod 先掌握一个概念,静态函数不属于它所在的那个类,它是独立于类的一个单独函数,只是寄存在一个类名下,先建立这个基本概念,后面学起来就简单很多了。
class My_Class(object):
# 类变量
cls_var = "类变量"def __init__(self):
# 在构造函数中创建变量
self.var = "实例变量"# 普通的对象实例函数
def instance_method(self):
# 可以访问类变量
print(self.cls_var)
# 可以访问实例变量
print(self.var)
print("实例化方法")@staticmethod
def static_method():
print(My_Class.cls_var)
# 无法访问到实例变量
# print(My_Class.var)
# print(self.var)
print("静态方法")my_class = My_Class()
my_class.instance_method()# 通过对象访问
my_class.static_method()
# 类名直接访问
My_Class.static_method()
即使修改成下述代码,也是错误的,静态函数的第一个参数不是实例对象
self
,或者可以理解为静态函数没有隐形参数,如需要传递参数,在参数列表中声明即可。@staticmethod
def static_method(self):
print(My_Class.cls_var)
# 无法访问到实例变量
# print(My_Class.var)
print(self.var)
print("静态方法")
在同一个类中,调用静态方法,使用
类名.函数名()
的格式。15.3 类函数与静态函数在继承类中的表现 先创建一个父类,其中包含两个静态函数与一个类函数。
class F(object):@staticmethod
def f_static(x):
print("静态方法,有 1 个参数")
print(f"f_static:{x}")@staticmethod
def f_static_1():
print("静态方法,无参数")
return F.f_static(10)@classmethod
def class_method(cls):
print("父类中的类方法")
return F.f_static(12)f = F()
f.f_static(11)
f.f_static_1()f.class_method()
再编写一个
S
类继承自 F
类:class S(F):@staticmethod
def f_static(y):
print("子类中重载了父类的静态方法")
print(f"子类中的参数{y}")@classmethod
def class_method(cls):
print("子类中的类方法")s = S()
s.f_static(110)
s.class_method()
S.class_method()
测试之后,基本结论如下:
如果在子类中覆盖了父类的静态函数,那调用时使用的是子类自己的静态函数,
如果在子类中没有覆盖父类的静态函数,那调用时使用的是父类的静态函数,
类函数同样遵循该规则。
如果希望在子类中调用父类的属性或者函数,请使用
父类名.
的形式实现。15.4 抽象函数 @abstractmethod 被
@abstractmethod
装饰的函数为抽象函数,含抽象函数的类不能实例化,继承了含抽象函数的子类必须覆盖所有抽象函数装饰的方法,未被装饰的可以不重写。抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化,实现代码如下:
import abcclass My_Class(abc.ABC):@abc.abstractmethod
def abs_method(self):
passdef show(self):
print("普通")class M(My_Class):
def abs_method(self):
print('xxx')mm = M()
mm.abs_method()
抽象基类中学习还需要了解元类相关知识,在第三轮滚雪球学 Python 中将为你展开这部分内容。
15.5 方法伪装属性 在 Python 面向对象的编码过程中,
对象.属性
来获取属性的值,使用 对象.方法()
来调用方法,通过装饰器 @property
可以将一个方法伪装成属性,从而使用 对象.方法
没有括号的形式调用。代码非常简单:class My_Class(object):def __init__(self, name):
self.__name = name@property
def name(self):
return self.__namem = My_Class("橡皮擦")
print(m.name)
这种写法最直接的应用,就是将部分属性变成只读属性,例如,上述代码,你无法通过下述代码对
name
进行修改。class My_Class(object):
def __init__(self, name):
self.__name = name@property
def name(self):
return self.__namem = My_Class("橡皮擦")
m.name = "擦哥擦姐"
print(m.name)
如果希望方法伪装的属性具备修改和删除功能,需要参考下述代码:
class My_Class(object):
def __init__(self, name):
self.__name = name@property
def name(self):
return self.__name@name.setter
def name(self, name):
self.__name = name@name.deleter
def name(self):
del self.__namem = My_Class("橡皮擦")
m.name = "擦哥擦姐"
print(m.name)
上述代码在将
name
方法伪装成属性之后,可以通过 @name.setter
和 @name.deleter
对同名的 name
方法进行装饰,从而实现了修改与删除功能。所以一般使用方法伪装属性的步骤是:
@property
装饰器,可以用来将类中的方法伪装成属性;@方法名.setter
装饰器,在修改伪装成属性的方法值时会调用它;@方法名.deleter
装饰器,在删除伪装成属性的方法值时会调用它。
property
函数,原型如下# 最后一个参数是字符串,调用 实例.属性.__doc__ 时的描述信息
property(fget=None, fset=None, fdel=None, doc=None)
通过上述函数将方法伪装成属性的代码为:
class My_Class(object):
def __init__(self, name):
self.__name = namedef del_name(self):
del self.__namedef set_name(self, name):
self.__name = namedef get_name(self):
return self.__name
# 将方法伪装成属性
name = property(get_name, set_name, del_name)
m = My_Class("梦想橡皮擦")
print(m.name)
m.name = "橡皮擦"
print(m.name)del m.name
15.6 这篇博客的总结 【#抬抬小手学Python# 类函数、成员函数、静态函数、抽象函数、方法伪装属性】滚雪球学 Python 第二轮 15 篇博客在一次结束了,学 Python 我们一直在路上,希望本系列的课程对你的 Python 学习有所助力。
推荐阅读
- [抬抬小手学Python]-Python基础
- 实战|Python轻松实现地图可视化(附详细源码)
- 手写一个 Python "病毒"
- 保姆级教学,手把手教你用Python爬虫(附详细源码)
- 用Python制作一个B站视频下载小工具
- 用Python分析广州房地产市场
- 【抬抬小手学Python】yolov3代码和模型结构图详细注解【图文】
- 【小手一抬学Python】Socket套接字编程Python
- #抬抬小手学Python# Python Poetry 进行依赖管理【图文】
- #小手一抬学Python# Python字典已经掌握了【附源码】