微信公众号搜索【程序媛小庄】,关注半路出家的程序媛如何靠python开发养家糊口~,
前言
面向对象编程有三大特性:封装、继承、多态,本文带大家来认识和了解这三个特性~
补充 - 新式类 & 经典类
在python2.x中,新式类是继承了object类的子类,以及该子类的子类 子子类…;经典类就是没有继承没有继承object类的子类,以及该子类的子类 子子类…。
在python3.x中,如果没有继承任何类,默认就会继承object类,没有经典类和新式类之分。
object类提供了一些常用内置方法的实现,比如用来在打印对象时返回字符串的内置方法__str__
,后续文章会做介绍的哦~
封装
封装是面向对象编程最重要的特性,封装就是将数据和功能整合到一起,就是我们之前说的将数据与功能装
在一起。
针对封装到对象或者类中属性,我们可以严格控制在类外部对它们的访问,即隐藏属性和开放接口。
隐藏属性
如何隐藏属性
在类体代码中,如果在一个属性名前加__
前缀,就会实现一个对外部隐藏该属性的效果,虽然在类外部无法直接通过对象.属性
的方式直接访问双下划线开头的属性,但是知道类名和属性名就可以得到外部访问类属性的方式即对象._类名__属性名
,所以说这种操作并没有严格意义上的限制外部访问类内部定义的属性。
这种隐藏对外不对内,这种变形操作只在检查类体语法的时候发生一次,在类外部定义的__开头的属性都不会发生变形
class Test():
__name = 'test' # 函数外部访问时变为_Test__name
def __init__(self):
self.__x = 'x'
def test(self):
self.__x = 'test' # 在类体代码内部可以正常使用属性
print('test')
print(Test.__name) # AttributeError: type object 'Test' has no attribute '__name'
print(Test._Test__name) # test
print(Test.__dict__)
mappingproxy(..., '_Test__name': 'test', '_Test__test': <function Test.__test at 0x0000026E75F6E3A0>, ...})
test_obj = Test()
test_obj.test() # 正常执行
print(test_obj.__x) # AttributeError: 'Test' object has no attribute '__x'
test_obj.__a = 'a' # 类外部定义的__的属性不会发生变形
print(test_obj.__a) # a
隐藏属性的目的
定义属性就是为了使用,所以隐藏并不是最终的目的,将数据属性隐藏起来就限制了了类外部对数据的直接操作,但是类内部应该提供相应的接口来允许类外部间接的操作数据,可以在接口上增加额外的逻辑来对外部操作类内定义的数据进行严格的控制。比如:
class People:
def __init__(self,name):
self.__name = name
def tell_info(self):
pwd = input('请输入暗号>>').strip()
if pwd == '0':
print(self.__name)
else:
print('暗号错误')
def set_name(self,new_name):
if type(new_name) is str:
self.__name = new_name
print(self.__name)
else:
print('请输入字符串')
p = People('python')
p.tell_info()
p.set_name(123)
隐藏函数属性的目的是只将用户用到的接口暴露出去,在该接口内可能会用到类内定义的其他方法,但是这些方法用户无需直接调用,就可以将这些方法进行隐藏,隔离程序的复杂度。
隐藏属性和暴露接口就是为了明确的区分类的内外部分,类的内部可以修改类内定义的数据但是不影响外部调用,类外部只需要有一个接口,只要接口的名字、参数不变,那么无论类内部的代码如何改变,外部调用方式都不会发生改变。
继承与派生
继承是创建新类的一种方式,通过继承得到的新类可以称为子类或者派生类,被继承的类被称为父类或者基类。
通过继承得到的子类会继承父类的所有属性,python支持多继承,子类可以继承一个或者多个父类。
通过使用类的继承,可以解决类与类之间的代码冗余问题。
类的继承语法如下:
class Parent1():
x = 111
class Parent2():
pass
class Foo(Parent1): # 单继承,父类是Parent1
pass
class Foo1(Parent1,Parent2): # 多进程,父类是Parent1 Parent2
pass
可以通过__bases__
查看子类继承的所有父类。
print(Foo.__bases__)
# (<class '__main__.Parent1'>,)
print(Foo1.__bases__)
# (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
如果想要找出类和类之间的关系,需要先总结一下多个类的相似之处,就可以得到父类,类与类之间的继承指的就是什么是什么
的关系,比如金毛是狗,狗是动物比如: