首先在python中,定义一个类,作为例子,然后引出相关知识点
class Example(object):
def __init__(self,data1,data2):
self.__data1=data1
self.data2=data2
def __func1(self):
print("Example类的私有方法可以被调用!")
def show_data(self):
self.__func1()
print(self.__data1)
print(self.data2)
exp= Example(50,100)
exp.show_data()
输出结果:
Example类的私有方法可以被调用!
50
100
这里,__init__是定义的类的构造函数,可以对类的变量进行初始化,只要类被实例化的时候,就会先执行构造函数。
类的实例化很简单,只要根据类的初始属性是否为空的情况决定。
比如1--类的初始状态为空:
class Example(object):
def __init__(self):
print("Example类的私有方法可以被调用!")
exp=Example()
输出结果:
Example类的私有方法可以被调用!
再比如2:类的初始状态不为空,需要传入属性:
class Example(object):
def __init__(self,data1,data2):
self.data1=data1
self.data2=data2
exp=Example(10,20)
exp.data1
输出结果:
10
在python中,类的封装有两层含义,一种是对数据的封装 ,一种是对实现逻辑方法的封装
比如1:对数据的封装
还是刚刚上面的那个例子:
class Example(object):
def __init__(self,data1,data2):
self.data1=data1
self.data2=data2
exp=Example(10,20)
exp.data1
在这个示例中,对象exp经过Example实例化后,就具有两个属性,即data1和data2,所以data1和data2就是对数据的封装。
再比如2:对逻辑的封装(对输入的两个数求和):
class Example(object):
def __init__(self,data1,data2):
self.data1=data1
self.data2=data2
def add(self):
print(self.data1+self.data2)
exp=Example(10,20)
exp.add()
输出结果:
30
上面的实例中,add函数实现了对两个数求和的功能,但是这个功能的实现,在类的外部是看不到这个过程的,当类被实例化后,类的对象调用这个函数时,会输出结果。这就是实现逻辑的封装。
继承是面向对象编程的重要组成部分。以下是一个简单实例。
class Father(object):
def __init__(self, age):
self.age=age
print ( "age: %d" %( self.age) )
def getAge(self):
return self.age
class Son(Father):
def __init__(self, age):
print ( "hello world" )
self.age = age
son=Son(18)
print (son.getAge())
输出结果:
hello world
18
这里,子类Son继承父类Father,因此子类可以使用父类所有公开方法,不需要再创建,比如这里子类直接调用父类的getAge方法。
此外,关于继承中的静态方法,类方法等知识,可以参考Python-实例方法静态方法类方法对比总结(附Python代码)
关于类的私有属性和私有方法,相对上述内容来说,要抽象一点。
Python 没有像C++,java那样明确的共有,私有,受保护的关键字来描述成员方法或属性,在Python中,它使用既定的单下划线"_"和双下划线"__"作为私有函数或属性的标识。这里使用单下划线还是双下划线有很大区别。
实例:
class Father():
def __private(self):
print("父类的私有函数private")
def _protected(self):
print("父类的受保护函数protected")
def public(self):
print("父类的公有函数public")
self.__private()
self._protected()
class Son(Father):
def __private(self):
print("子类的重载私有函数private")
def _protected(self):
print("子类的重载受保护protected")
s = Son()
s.public()
输出结果:
父类的公有函数public
父类的私有函数private
子类的重载受保护protected
上面的例子中,父类的public是共有函数,可以被子类直接调用,__private是父类的私有方法,不可以在类外调用,但是可以通过类内的public方法调用__private,即使私有方法可以在类的内部被调用。
继续上面的例子,我们重新输入:
s = Son()
# s.public()
s._protected()
输出结果:
子类的重载受保护protected
从结果中,我们发现子类的单下划线方法_protected覆盖了父类的_protected方法,但是上面的例子中是输出的是父类Father的私有函数__private,也就意味着子类没有覆盖父类的__private方法,即:父类的双下划线__private只能被自身访问。那么如何子类如何调用自身的__private函数呢?
我们重新输入:
s = Son()
# s.public()
# s._protected()
s._Son__private()
输出结果:
子类的重载私有函数private
结果正是我们想要的:子类Son输出的是自身的__private函数。
对比两个结果说明:子类双划线方法__private方法并没有覆盖父类双下划线__private方法的权限,但是子类的单下划线方法_protected方法是可以覆盖父类的单下划线_protected方法
继续追问,既然子类普通函数和单下划线函数都可以覆盖父类的普通函数和单下划线函数,那么普通函数和单下划线受保护函数之间有什么区别呢?
其实,在同一个py脚本下看不出区别,但是如果py作为模块导入的时候,单下划线不能导入到模块,即:_protected 不能用于’from module import *’ 以单下划线开头的表示的是protected类型的变量。即受保护类型只能允许其本身与子类进行访问。
接着我们重新看刚刚上面输入的s._Son__private(),为什么实例后面要跟上一个单下划线和一个类名呢?
实际上,Python使用名字混淆的方法,将双下划线私有方法"__method"编程了"_claseename__method"了。
所以不要在一个类中同时使用__method和 _ClassName__method
例如,下面这样的程序就会报错
class example():
def _protected(self):
print("example 保护函数")
def __private(self):
print("正常 私有函数")
def _example__private(self):
print("特殊 _example__private")
def public(self):
print(" 共有函数")
self.__hide()
example().public()
报错的输出结果:
共有函数
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
in ()
13 self.__hide()
14
---> 15 example().public()
in public(self)
11 def public(self):
12 print(" 共有函数")
---> 13 self.__hide()
14
15 example().public()
AttributeError: 'example' object has no attribute '_example__hide'
以上是个人总结的相关python的基础类实例,继承,私有函数,私有变量等。
此外关于静态方法,类方法和实例方法内容;类的继承,调用父类的属性和方法基础讲解,可以参考:
Python-实例方法静态方法类方法对比总结(附Python代码)
Python:类的继承,调用父类的属性和方法基础详解