python面向对象编程基础II(类的继承)

继承一个类

继承的好处:

1、复用已有代码

2、自动拥有现有类的所有功能

3、只需要编写缺少的功能

如果已经定义了Person类,需要定义新的StudentTeacher类时,可以直接从Person类继承:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

定义Student类时,只需要把额外的属性加上,例如score:

class Student(Person):
    def __init__(self, name, gender, score):
        super(Student, self).__init__(name, gender)
        self.score = score

一定要用 super(Student, self).__init__(name, gender) 去初始化父类,否则,继承自 Person 的 Student 将没有 name 和 gender

函数super(Student, self)将返回当前类继承的父类,即 Person ,然后调用__init__()方法,注意self参数已在super()中传入,在__init__()中将隐式传递,不需要写出(也不能写)。

函数isinstance()可以判断一个变量的类型,既可以用在Python内置的数据类型如str、list、dict,也可以用在我们自定义的类,它们本质上都是数据类型。所以可以用

isinstance(t,Person)判断对象t是不是Person类型。

多态

类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 StudentTeacher ,并都写了一个 whoAmI() 方法:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def whoAmI(self):
        return ‘I am a Person, my name is %s‘ % self.name

class Student(Person):
    def __init__(self, name, gender, score):
        super(Student, self).__init__(name, gender)
        self.score = score
    def whoAmI(self):
        return ‘I am a Student, my name is %s‘ % self.name

class Teacher(Person):
    def __init__(self, name, gender, course):
        super(Teacher, self).__init__(name, gender)
        self.course = course
    def whoAmI(self):
        return ‘I am a Teacher, my name is %s‘ % self.name

在一个函数中,如果我们接收一个变量 x,则无论该  Person、Student还是 Teacher,都可以正确打印出结果:

def who_am_i(x):
    print x.whoAmI()

p = Person(‘Tim‘, ‘Male‘)
s = Student(‘Bob‘, ‘Male‘, 88)
t = Teacher(‘Alice‘, ‘Female‘, ‘English‘)

who_am_i(p)
who_am_i(s)
who_am_i(t)

运行结果:

I am a Person, my name is Tim
I am a Student, my name is Bob
I am a Teacher, my name is Alice

这种行为称为多态。也就是说,方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。

由于Python是动态语言,所以,传递给函数 who_am_i(x)的参数x 不一定是 Person 或 Person 的子类型。任何数据类型的实例都可以,只要它有一个whoAmI()的方法即可:

class Book(object):
    def whoAmI(self):
        return ‘I am a book‘

这是动态语言和静态语言(例如Java)最大的差别之一。动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。

多重继承

除了从一个父类继承外,Python允许从多个父类继承,称为多重继承。

多重继承的继承链就不是一棵树了,它像这样:

class A(object):
    def __init__(self, a):
        print ‘init A...‘
        self.a = a

class B(A):
    def __init__(self, a):
        super(B, self).__init__(a)
        print ‘init B...‘

class C(A):
    def __init__(self, a):
        super(C, self).__init__(a)
        print ‘init C...‘

class D(B, C):
    def __init__(self, a):
        super(D, self).__init__(a)
        print ‘init D...‘

看下图:

像这样,同时继承自 B 和 C,也就是 D 拥有了 A、B、C 的全部功能。多重继承通过 super()调用__init__()方法时,A 虽然被继承了两次,但__init__()只调用一次:

>>> d = D(‘d‘)
init A...
init C...
init B...
init D...

多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用。

举个例子,Python的网络服务器有TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer,而服务器运行模式有 多进程ForkingMixin 和 多线程ThreadingMixin两种。

要创建多进程模式的 TCPServer

class MyTCPServer(TCPServer, ForkingMixin)
    pass

要创建多线程模式的 UDPServer

class MyUDPServer(UDPServer, ThreadingMixin):
    pass

如果没有多重继承,要实现上述所有可能的组合需要 4x2=8 个子类。

获取对象信息

拿到一个变量,除了用 isinstance() 判断它是否是某种类型的实例外,还有没有别的方法获取到更多的信息呢?

例如,已有定义:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

class Student(Person):
    def __init__(self, name, gender, score):
        super(Student, self).__init__(name, gender)
        self.score = score
    def whoAmI(self):
        return ‘I am a Student, my name is %s‘ % self.name

首先可以用 type() 函数获取变量的类型,它返回一个 Type 对象:

>>> type(123)
<type ‘int‘>
>>> s = Student(‘Bob‘, ‘Male‘, 88)
>>> type(s)
<class ‘__main__.Student‘>

其次,可以用 dir() 函数获取变量的所有属性:

>>> dir(123)   # 整数也有很多属性...
[‘__abs__‘, ‘__add__‘, ‘__and__‘, ‘__class__‘, ‘__cmp__‘, ...]

>>> dir(s)
[‘__class__‘, ‘__delattr__‘, ‘__dict__‘, ‘__doc__‘, ‘__format__‘, ‘__getattribute__‘, ‘__hash__‘, ‘__init__‘, ‘__module__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘__weakref__‘, ‘gender‘, ‘name‘, ‘score‘, ‘whoAmI‘]

对于实例变量,dir()返回所有实例属性,包括`__class__`这类有特殊意义的属性。注意到方法`whoAmI`也是 的一个属性。

如何去掉`__xxx__`这类的特殊属性,只保留我们自己定义的属性?回顾一下filter()函数的用法。

dir()返回的属性是字符串列表,如果已知一个属性名称,要获取或者设置对象的属性,就需要用 getattr()  setattr( )函数了:

>>> getattr(s, ‘name‘)  # 获取name属性
‘Bob‘

>>> setattr(s, ‘name‘, ‘Adam‘)  # 设置新的name属性

>>> s.name
‘Adam‘

>>> getattr(s, ‘age‘)  # 获取age属性,但是属性不存在,报错:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ‘Student‘ object has no attribute ‘age‘

>>> getattr(s, ‘age‘, 20)  # 获取age属性,如果属性不存在,就返回默认值20:
20
时间: 2024-10-10 06:33:21

python面向对象编程基础II(类的继承)的相关文章

[.net 面向对象编程基础] (9) 类的成员(字段、属性、方法)

[.net 面向对象编程基础] (9) 类的成员(字段.属性.方法) 前面定义的Person的类,里面的成员包括:字段.属性.方法.事件等,此外,前面说的嵌套类也是类的成员. a.类的成员为分:静态成员(static)和非静态成员 b.静态成员用static标识,不标识则默认为非静态成员 c.静态成员属于类所有,动态成员则属于实例所有,即对象 d.静态成员为类所有实例共享,无论类有多少实例或副本,静态成员只占用存中一块区域.非静态成员则在类的每个实例,都创建一个内存域. 下面主要说明一下类的主要

4.python面向对象编程基础

4.1 面向对象编程的基本思想 类用来定义抽象类型 实例的一个类的具有实现 python中 class Person: pass 数据封装 class Person: def __init__(self, name,age ) self.name = name self.age = age p = Person('xiaoming',23) 4.2类的定义与创建实例 在Python中,类通过 class 关键字定义.以 Person 为例,定义一个Person类如下: class Person(

Python 面向对象编程基础

活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法. 把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派. 这样一说是不是更不明白了.所以

Python面向对象编程基础

面向对象关键词:类,对象,实例,方法 面向对象三大特性:封装,继承,多态 class Foo: # 定义类名 def f1(self): # f1方法 print("success") obj = Foo() # 创建对象 obj.f1() # 通过对象执行方法 类和对象的关系: self参数是一个Python自动会传值的参数,那个对象执行方法,self就是那个 class SQLhelp(): def __init__(self, a1, a2, a3): # 此方法会自动执行,那个

Python 面向对象编程基础——初始化实例、类属性、方法

#1.初始化实例化属性.#可接受任意关键字参数,并把他们都作为属性赋值给实例.使用**kw,除了可以直接使用self.name = 'xxx'设置一个属性外,还可以通过setattr(self, 'name', 'xxx')设置属性.class Person(object):    def __init__(self, name, gender, **kw):        self.name = name        self.gender = gender        for k,v i

python 面向对象编程 之 元类

元类是类的类,使我们自定义的类,即我们用class定义类本质就是元类,是类的模板 四步走: 一:控制class定义类的过程 1.先拿到类名 2.在拿到基类 3.执行类体代码,得到名称空间的dict 4.调用元类将三个参数传递进去 #其实class 是上面四步的封装.(隔离了复杂度) 二:自定义元类 class Mymeta(type): def __init__(self,class_name,class_base,class_dic): super().__init__(class_name,

python学习第十四天 -面向对象编程基础

python也是支持面向对象编程的.这一章节主要讲一些python面向对象编程的一些基础. 什么是面向对象的编程? 1.面向对象编程是一种程序设计范式 2.把程序看做不同对象的相互调用 3.对现实世界建立对象模型 面向对象编程的基本思想: 1.类用于定义抽象类型 2.实例根据类的定义被创建出来 如何定义一个类并创建实例? >>> class Animal(object): pass >>> dog = Animal() >>> cat = Animal

JAVA学习(五):Java面向对象编程基础

Java面向对象编程基础 面向对象(Object oriented programming,OOP)技术是一种强有力的软件开发方法,它採用数据抽象与信息隐藏技术,来使软件开发简单化,以达到代码重用的目的. 1.OOP的3个特性(封装.继承和多态性) 封装是类的基础.指把类的相关实现细节隐藏起来,在类中将数据和实现操作的代码集中起来放在对象的内部.调用这些类时仅仅需直接使用类预留的接口就能够了. 继承提供了子类自己主动拥有父类数据结构和方法的机制.它表示类之间的一种关系. 多态指使一个对象被看成还

[.net 面向对象编程基础] (20) LINQ使用

[.net 面向对象编程基础] (20)  LINQ使用 通过上节LINQ的基础知识的学习,我们可以开始使用LINQ来进行内存数据的查询了,我们上节说了LINQ的定义为:Language Integrated Query(语言集成查询)的简称,它是集成在.NET编程语言中的一种特性. 1.LINQ的构架 从这幅图中,我们可以知道LINQ包括五个部分:LINQ to Objects.LINQ to XML.LINQ to SQL.LINQ to DataSet.LINQ to Entities.