📜  Python中的面向对象编程OOP | 3(继承,对象示例,issubclass和super)

📅  最后修改于: 2020-04-07 10:10:44             🧑  作者: Mango

我们已经讨论了以下有关Python中的面向对象编程的主题:

在本文中,介绍了继承。
面向对象编程的主要优点之一是重用。继承是实现重用的机制之一。在继承中,一个类(通常称为超类)被另一个类(通常称为子类)继承。子类将一些属性添加到超类。
以下是一个示例Python程序,用于显示如何在Python中实现继承。

# Python展示继承
# Python 3.x中"class Person" 等效于
# "class Person(对象)"
class Person(object):
    # 构造函数
    def __init__(self, name):
        self.name = name
    # 获取name
    def getName(self):
        return self.name
    # 检查这个person是否是employee
    def isEmployee(self):
        return False
# 继承类
class Employee(Person):
    # 返回True
    def isEmployee(self):
        return True
# 测试代码
emp = Person("芒果1")  # Person对象
print(emp.getName(), emp.isEmployee())
emp = Employee("芒果2") #  Employee对象
print(emp.getName(), emp.isEmployee())

输出:

('芒果1', False)
('芒果2', True)

如何检查一个类是否是另一个的子类?
Python提供了一个函数issubclass(),它可以直接告诉我们一个类是否是另一个类的子类。

# Python检查一个类是否是另一个的子类
class Base(object):
    pass   # 空类
class Derived(Base):
    pass   # 空类
# 测试代码
print(issubclass(Derived, Base))
print(issubclass(Base, Derived))
d = Derived()
b = Base()
# b 不是派生类对象
print(isinstance(b, Derived))
# d是Base的对象
print(isinstance(d, Base))

输出:

True
False
False
True

什么是对象类?
像Java对象类一样,在Python(3.x版及更高版本)中,对象是所有类的父类。
在Python 3.x中,“class Test(object)”和“class Test”相同。
在Python 2.x中,“class Test(object)”创建一个以对象为父类的类(称为新样式类),而“class Test”创建一个旧样式类(不带对象父类)。有关更多详细信息,请参考内容。

Python是否支持多重继承?
与Java和C++不同,Python支持多重继承。我们将所有父类指定为括号中的逗号分隔列表。

# Python展示多重继承
class Base1(object):
    def __init__(self):
        self.str1 = "芒果1"
        print "父类1"
class Base2(object):
    def __init__(self):
        self.str2 = "芒果2"
        print "父类2"
class Derived(Base1, Base2):
    def __init__(self):
        # 调用父类1和父类2的构造函数
        Base1.__init__(self)
        Base2.__init__(self)
        print "派生类"
    def printStrs(self):
        print(self.str1, self.str2)
ob = Derived()
ob.printStrs()

输出:

父类1
父类2
派生类
('芒果1', '芒果2')

如何访问子类中的父成员?
1,使用父类名称 

# Python访问子类中的父成员
class Base(object):
    # 构造函数
    def __init__(self, x):
        self.x = x
class Derived(Base):
    # 构造函数
    def __init__(self, x, y):
        Base.x = x
        self.y = y
    def printXY(self):
       # print(self.x, self.y),也会奏效
       print(Base.x, self.y)
# 测试代码
d = Derived(10, 20)
d.printXY()

输出: 

(10, 20)

 2,使用super()
我们还可以使用super访问父类成员。 

# Python展示使用super访问父类成员
class Base(object):
    # 构造函数
    def __init__(self, x):
        self.x = x
class Derived(Base):
    # 构造函数
    def __init__(self, x, y):
        '''Python 3.x, "super().__init__(name)"
            也会奏效'''
        super(Derived, self).__init__(x)
        self.y = y
    def printXY(self):
       # 注意Base.x在这里不会奏效
       # 因为super()在构造函数中被使用
       print(self.x, self.y)
# 测试代码
d = Derived(10, 20)
d.printXY()

输出: 

(10, 20)

请注意,上述两种方法并不完全相同。在下一篇关于继承的文章中,我们将介绍以下主题。
1)super如何运作?通过超级类和父类名称访问成员的方式有何不同?
2)如何用Python处理Diamond问题?

练习:
预测以下Python程序的输出  

class X(object):
    def __init__(self, a):
        self.num = a
    def doubleup(self):
        self.num *= 2
class Y(X):
    def __init__(self, a):
        X.__init__(self, a)
    def tripleup(self):
        self.num *= 3
obj = Y(4)
print(obj.num)
obj.doubleup()
print(obj.num)
obj.tripleup()
print(obj.num)

输出: 

4
8
24

 另一个例子:

# 父类或基类
class Person(object):
    def __init__(self, name):
        self.name = name
    def getName(self):
        return self.name
    def isEmployee(self):
        return False
# 继承
class Employee(Person):
    def __init__(self, name, eid):
        '''Python 3.0+, "super().__init__(name)"
            也会奏效'''
        super(Employee, self).__init__(name)
        self.empID = eid
    def isEmployee(self):
        return True
    def getID(self):
        return self.empID
# 测试代码
emp = Employee("芒果1", "E101")
print(emp.getName(), emp.isEmployee(), emp.getID())

输出: 

('芒果1', True, 'E101')