封装、继承、多态
面向对象编程有三大重要特征:封装、继承和多态。
继承
继承机制实现了代码的复用,多个类公用的代码部分可以只在一个类中提供,而其他类只需要继承这个类即可。
在OOP程序设计中,当我们定义一个新类的时候,新的类称为子类(Subclass),而被继承的类称为基类、父类或超类(Base class、Super class)。继承最大的好处是子类获得了父类的全部变量和方法的同时,又可以根据需要进行修改、拓展。其语法结构如下:
class Foo(superA, superB,superC....):
class DerivedClassName(modname.BaseClassName): ## 当父类定义在另外的模块时
Python3,在定义一个类的时候,如果没有继承的话可以写上object。
写不写object都可以,但是建议大家写。
# 父类定义
class people:
def __init__(self, name, age, weight):
self.name = name
self.age = age
self.__weight = weight
def speak(self):
print("%s 说: 我 %d 岁。" % (self.name, self.age))
# 单继承示例
class student(people):
def __init__(self, name, age, weight, grade):
# 调用父类的实例化方法
people.__init__(self, name, age, weight)
self.grade = grade
# 重写父类的speak方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级" % (self.name, self.age, self.grade))
s = student('ken', 10, 30, 3)
s.speak()
python3的继承机制
Python3的继承机制不同于Python2。其核心原则是下面两条,请谨记!
1.子类在调用某个方法或变量的时候,首先在自己内部查找,如果没有找到,则开始根据继承机制在父类里查找。
2.根据父类定义中的顺序,以深度优先的方式逐一查找父类!
super()函数:
我们都知道,在子类中如果有与父类同名的成员,那就会覆盖掉父类里的成员。那如果你想强制调用父类的成员呢?使用super()函数!
语法:super(子类名, self).方法名()
,需要传入的是子类名和self,调用的是父类里的方法,按父类的方法需要传入参数。
class A:
def __init__(self, name):
self.name = name
print("父类的__init__方法被执行了!")
def show(self):
print("父类的show方法被执行了!")
class B(A):
def __init__(self, name, age):
super(B, self).__init__(name=name)
self.age = age
def show(self):
# 第一种方式
A.show(self)
# 第二种方式
super(B, self).show()
obj = B("jack", 18)
obj.show()
私有方法和属性的继承
class A:
self.num = 100
self.__num2 = 100
def test1(self):
print("--test1--")
def __test2(self):
print("--test2--")
def test3(self):
self.__test2()
print(self.__num2)
class B(A):
def test4(self):
self.__test2()
print(self.__num2)
b = B()
b.test1()
b.__test2()
print(b.num)
print(b.__num2)
b.test3()
如果调用的是继承的父类中的方法,可以在这个公有方法中访问父类中的私有属性和私有方法
但是如果在子类中实现了一个公有方法,那么这个方法是不能够调用继承的父类中的私有方法和私有属性的
多继承
class Base(object):
def test(self):
print("--base--")
class A(Base):
def test1(self):
print("--test1--")
class B(Base):
def test2(self):
print("--test2--")
class C(A,B):
pass
c = C()
c.test1()
c.test2()
c.test()
- 注意
如果C类中的方法跟A,B,Base类中的方法都重名的话,调用时的顺序是怎么样的?
类名.__mro__
print(C.__mro__)
决定调用方法的时候,搜索的顺序,如果在某个类中找到了方法,那么就停止搜索
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)
多态
多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚"鸭子类型"
动态语言调用实例方法时不检查类型,只要方法存在,参数正确,就可以调用。这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态。
class Dog(object):
def print_self(self):
print("大家好,我是xxxx")
# 继承Dog类
class Xiaotq(Dog):
def print_self(self):
print("大家好,我是你们的老大")
def info(obj):
obj.print_self()
dog = Dog()
dog1 = Xiaotq()
info(dog)
info(dog1)
封装
封装是指将数据与具体操作的实现代码放在某个对象内部,使这些代码的实现细节不被外界发现,外界只能通过接口使用该对象,而不能通过任何形式修改对象内部实现,正是由于封装机制,程序在使用某一对象时不需要关心该对象的数据结构细节及实现操作的方法。
class Student:
classroom = '101'
address = 'beijing'
def __init__(self, name, age):
self.name = name
self.age = age
def print_age(self):
print('%s: %s' % (self.name, self.age))
# 以下是错误的用法
# 类将它内部的变量和方法封装起来,阻止外部的直接访问
print(classroom)
print(adress)
print_age()
网友评论