PYTHON小白:第十六天

PYTHON小白:第十六天
1、 隐藏和封装
封装(Encapsulation)是面向对象的三大特征之一(另外两个是继承和多态),它指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。
封装是面向对象编程语言对客观世界的模拟,在客观世界里,对象的状态信息都被隐藏在对象内部,外界无法直接操作和修改。对一个类或对象实现良好的封装,可以达到以下目的。
 隐藏类的实现细节。
 让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里加入控制逻辑,限制对属性的不合理访问。
 可进行数据检查,从而有利于保证对象信息的完整性。
 便于修改,提高代码的可维护性。
为了实现良好的封装,需要从两个方面来考虑:
 将对象的属性和实现细节隐藏起来,不允许外部直接访问。
 把方法暴露出来,让方法来控制对这些属性进行安全的访问和操作。
因此,实际上封装有两个方面的含义:把该隐藏的隐藏起来,把该暴露的暴露出来。
Python并没有提供类似于其他语言的private等修饰符,因此Python并不能真正支持隐藏。
为了隐藏类中的成员,Python玩了一个小技巧,只要将Python的成员命名为以双下画线开头的,Python就会把它们隐藏起来。

上面程序将User的两个实例变量,分别命名为__name和_age这两个实例变量会被隐藏起来,这样程序就无法直接访问_name、_age变量,只能通过setname()、getname()、setage()、getage这些访问器方法进行访问,而setname(),setage()会对用户设置的name、age进行控制,只有符合条件的name和age才允许设置。

从该程序可以看出封装的好处,程序可以将User对象的实现细节隐藏起来,程序只能通过暴露出来的setname()、setage()方法来改变User对象的状态,而这两个方法可以添加自己的逻辑控制,这种控制对User修改始终是安全的。

最后需要说明的是,Python其实没有真正的隐藏机制,双下画线只是Python的一个小技巧,Python会“偷偷”地改变以双下画线开头的方法名,会在这些方法名前添加单下画线和类名。

通过上面调用可以看出Python并没有实现真正的隐藏。
类似的是,程序也可通过为隐藏的实例变量添加下画线和类名的方式来访问或修改对象的实例变量。

总结:Python并没有提供真正的隐藏机制,所以Python类定义的所有成员默认都是公开的;如果程序希望将Python类中的某些成员隐藏起来,那么只要让该成员的名字以双下画线开头即可,即使通过这种机制实现了隐藏,其实也依然司以绕过去。
2、 类的继承
继承是面向对象的三大特征之一,也是实现软件复用的重要手段。Python的继承是多继承机制,即一个子类可以同时有多个直接父类。
2.1 继承的语法
Python子类继承父类的语法是在定义子类时,将多个父类放在子类之后的圆括号里。语法格式如下:

如果在定义Python时并未显式指定这个类的直接父类,则这个类默认继承object类。object类是所有类的父类,要么是其直接父类,要么是其间接父类。
实现继承的类被称为子类,被继承的类被称为父类,也被称为基类、超类。父类和子类的关系,是一般和特殊的关系。例如水果和苹果的关系,苹果继承了水果,苹果是水果的子类,则苹果是一种特殊的水果。
由于子类是一种特殊的父类,因此父类包含的范围总比子类包含的范围要大,所以可以认为父类是大类,而子类是小类。
从实际意义上看,子类是对父类的扩展,子类是一种特殊的父类。从这个意义上看,使用继承来描述子类和父类的关系是错误的,用扩展更恰当。因此,这样的说法更加准确Apple类扩展了Fruit类。
从子类的角度来看,子类扩展(extend)了父类,但从父类的角度来看父类派生(derive)出子类。也就是说,扩展和派生所描述的是同一个动作,只是观察角度不同而己。

继承的作用–子类扩展(继承〉了父类,将可以继承得到父类定义的方法,这样子类就可复用父类的方法了。
2.2 关于多继承
Python虽然在语法上明确支持多继承,但通常推荐:如果不是很有必要,则尽量不要使用多继承,而是使用单继承,这样可以保证编程思路更清晰,而且可以避免很多麻烦。
当一个子类有多个直接父类时,该子类会继承得到所有父类的方法,这一点在前面示例中己经做了示范。现在的问题是:如果多个父类中包含了同名的方法,此时会发生什么呢?此时排在前面的父类中的方法会“遮蔽”排在后面的父类中的同名方法。

2.3 重写父类的方法
子类扩展了父类,子类是一种特殊的父类。大部分时候,子类总是以父类为基础,额外增加新的方法。但有一种情况例外:子类需要重写父类的方法。例如鸟类都包含了飞翔方法,其中驼鸟是一种特殊的鸟类,因此驼鸟应该是鸟的子类,它也将从鸟类获得飞翔方法,但这个飞翔方法明显不适合驼鸟,为此,驼鸟需要重写鸟类的方法。

这种子类包含与父类同名的方法的现象被称为方法重写(Override),也被称为方法覆盖。可以说子类重写了父类的方法,也可以说子类覆盖了父类的方法。
2.4 使用未绑定方法调用被重写的方法
如果在子类中调用重写之后的方法,Python总是会执行子类重写的方法,不会执行父类中被重写的方法。如果需要在子类中调用父类中被重写的实例方法,那该怎么办呢?
Python类相当于类空间,因此Python类中的方法本质上相当于类空间内的函数。所以,即使是实例方法,Python允许通过类名调用。区别在于,在通过类名调用实例方法时Python不会为实例方法的第一个参数self自动绑定参数值,而是需要程序显式绑定第一个参数self,这种机制被称为未绑定方法。
通过使用未绑定方法即可在子类中再次调用父类中被重写的方法。

2.5 使用super函数调用父类的构造方法
Python的子类也会继承得到父类的构造方法,如果子类有多个直接父类,那么排在前面的父类的构造方法会被优先使用。

如果交换一下继承父类的位置。

为了让Manager同时初始化两个父类中的实例变量,Manager应该定义自己的构造方法–就是重写父类的构造方法。Python要求:如果子类重写了父类的构造方法,那么子类的构造方法必须调用父类的构造方法。子类的构造方法调用父类的构造方法有两种方式。
 使用未绑定方法,这种方式很容易理解。因为构造方法也是实例方法,当然可以通过这种方式来调用。
 使用super()函数调用父类的构造方法。
使用super()构造方法最常用的做法就是不传入任何参数(这种做法与super(type,obj)的效果相同),然后通过super对象的方法既可调用父类的实例方法,也可调用父类的类方法。在调用父类的实例方法时,程序会完成第一个参数self的自动绑定。在调用类方法时,程序会完成第一个参数cls的自动绑定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值