类在很多编程语言中基本上都会涉及,也非常有用。如果你是 Java 或者 Scala 语言的使用者,那么一定很熟悉类的私有方法(通常是以private
进行修饰),但是 Python 中如何创建私有方法,这是很多 Python 学习者经常会忽略的地方,本篇文章我们来做一个详细的介绍。
1. 使用场景
相信很多同学和我之前一样,在进行类方法编写的时候,并不会过多关注方法的访问权限,总觉得所有方法都可以被类的实例所访问不是挺好的么,且这种想法在工作种一直伴随我很久。直到我开始自己整理一些日常工具,并进行包的发版,我才发现很多类方法是没有必要呈现给使用者的(因为这些方法单独使用的场景非常少),熟练地使用类私有方法有以下有点:
- 可以让整个类的设计变得非常清晰,只暴露必要的类方法出来
- 使用者也倾向于只需要了解必要的函数功能
下面我们来看一个示例,想要实现查询指定学生 ID 的成绩和年龄,但首先需要判断该学生 ID 是否存在:
class Person(object):
def __init__(self, student_id):
self.student_id = student_id
def get_score(self):
is_exists = db.query("SELECT score FROM students WHERE student_id = %s" % self.student_id)
score = db.query("SELECT score FROM score WHERE student_id = %s" % self.student_id) if is_exists else None
return score
def get_age(self):
is_exists = db.query("SELECT score FROM students WHERE student_id = %s" % self.student_id)
age = db.query("SELECT FROM info WHERE student_id = %s" % self.student_id) if is_exists else None
return age
可以看出无论是查询成绩还是年龄,都先需要判断该学生 ID 是否存在,那么我们首先将判断学生 ID 是否存在封装成函数:
class Person(object):
def __init__(self, student_id):
self.student_id = student_id
def is_exists(self):
is_exists = db.query("SELECT score FROM students WHERE student_id = %s" % self.student_id)
return True if is_exists else False
def get_score(self):
score = db.query("SELECT score FROM score WHERE student_id = %s" % self.student_id) if self.is_exists() else None
return score
def get_age(self):
age = db.query("SELECT FROM info WHERE student_id = %s" % self.student_id) if self.is_exists() else None
return age
p = Person(10000)
p.is_exists() # False
但这个有个问题就是,我们在实例化Person
类时,所构造的实例是可以直接使用is_exists
函数,但是作为使用者来说,其实我们值关注于如何获取成绩和年龄,并不需要判断是否存在这个函数,所以下面我们将其改造成私有方法。
2. 私有方法
在 Python 类当中,如果方法名以双下划线(__
)开始,但不以双下划线(__
)结尾,这类方法称之为类的私有方法。如果方法名以双下划线开始和结尾的话,我们则称之为类的构造方法。
类的私有方法不可以从该类外面进行调用,即使是类的实例也不可以,对私有方法的调用只能存在于该类之内,这一点和类的私有属性基本一致。
class Person(object):
def __init__(self, student_id):
self.student_id = student_id
def __is_exists(self):
is_exists = db.query("SELECT score FROM students WHERE student_id = %s" % self.student_id)
return True if is_exists else False
def get_score(self):
score = db.query("SELECT score FROM score WHERE student_id = %s" % self.student_id) if self.__is_exists() else None
return score
def get_age(self):
age = db.query("SELECT FROM info WHERE student_id = %s" % self.student_id) if self.__is_exists() else None
return age
p = Person(10000)
p.__is_exists() # AttributeError: 'Person' object has no attribute '__is_exists'
再次调用__is_exists
方法时,解释器鬼告诉我们Person
类没有这个属性,这样使用起来我们只会看到该类有get_score
和get_age
2 个方法,整个类就变得非常干净。