继承和多态

在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Superclass)。

>>> class Animal(object):#名为Animal的class

defrun(self):

print'Animal is running...'

>>> class Dog(Animal):#从Animal类继承

pass

>>> dog=Dog()

>>> dog.run()#子类获得了父类的全部功能

Animal is running...

>>> class Dog(Animal):#对子类增加一些方法

defrun(self):

print'Dog is running...'

>>> dog=Dog()

>>> dog.run()

Dog is running...

多态

a = list() # a是list类型

b = Animal() # b是Animal类型

c = Dog() # c是Dog类型

>>> isinstance(a, list)

True

在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行:

>>> b = Animal()

>>> isinstance(b, Dog)

False

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写;有了继承,才能有多态。在调用类实例方法的时候,尽量把变量视作父类类型,这样,所有子类类型都可以正常被接收;

使用type()

判断对象类型,使用type()函数:

>>> type(123)#基本类型都可以用type()判断

<type 'int'>

>>> type('str')

<type 'str'>

>>> type(None)

<type 'NoneType'>

>>> type(abs)#变量指向函数或者类,也可以用type()判断

<type 'builtin_function_or_method'>

>>> type(a)

<class '__main__.Animal'>

>>> type(123)==type(456)#比较两个变量的type类型是否相同

True

>>> import types#Python把每种type类型都定义好了常量,放在types模块里

>>> type('abc')==types.StringType

True

>>> type(u'abc')==types.UnicodeType

True

>>> type([])==types.ListType

True

>>> type(str)==types.TypeType

True

>>> type(int)==type(str)==types.TypeType#特殊的类型

True

使用isinstance()

isinstance()可以告诉我们,一个对象是否是某种类型。他判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。

>>> isinstance(d, Dog) and isinstance(d,Animal)

True

>>> isinstance('a', str)

True#能用type()判断的基本类型也可以用isinstance()判断

>>> isinstance('a', (str, unicode))

True# 判断一个变量是否是某些类型中的一种

>>> isinstance(u'a', basestring)

True#str和unicode都是从basestring继承下来的

使用dir()

>>> dir('ABC')#获得一个str对象的所有属性和方法

['__add__', '__class__', '__contains__','__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__','__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__','__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__','__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__','__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split','_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode','endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha','isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower','lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition','rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase','title', 'translate', 'upper', 'zfill']

类似__xxx__的属性和方法在Python中都是有特殊用途的,比如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法,所以,下面的代码是等价的:

>>> len('ABC')

3

>>> 'ABC'.__len__()

3

我们自己写的类,如果也想用len(myObj)的话,就自己写一个__len__()方法:

>>> class MyObject(object):

def__len__(self):

return 100

>>> obj = MyObject()

>>> len(obj)

100

配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:

class MyObject(object):

def__init__(self):

self.x = 9

defpower(self):

return self.x * self.x

>>> hasattr(obj, 'x') # 有属性'x'吗?

True

>>> obj.x

9

>>> hasattr(obj, 'y') # 有属性'y'吗?

False

>>> setattr(obj, 'y', 19) # 设置一个属性'y'

>>> hasattr(obj, 'y') # 有属性'y'吗?

True

>>> getattr(obj, 'y') # 获取属性'y'

19

>>> obj.y # 获取属性'y'

19

>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404

404

>>> hasattr(obj, 'power') # 有属性'power'吗?

True

>>> getattr(obj, 'power') # 获取属性'power'

<bound method MyObject.power of<__main__.MyObject object at 0x108ca35d0>>

>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn

>>> fn # fn指向obj.power

<bound method MyObject.power of<__main__.MyObject object at 0x108ca35d0>>

>>> fn() # 调用fn()与调用obj.power()是一样的

81

使用__slots__

>>> class Student(object):

pass

>>> s = Student()

>>> s.name = 'Michael' # 动态给实例绑定一个属性

>>> print s.name

Michael

>>> def set_age(self, age): # 定义一个函数作为实例方法

self.age = age

>>> from types import MethodType

>>> s.set_age = MethodType(set_age, s,Student) # 给实例绑定一个方法

>>> s.set_age(25) # 调用实例方法

>>> s.age # 测试结果

25

但是,给一个实例绑定的方法,对另一个实例是不起作用的:

>>> s2 = Student() # 创建新的实例

>>> s2.set_age(25) # 尝试调用方法

Traceback (most recent call last):

File"<stdin>", line 1, in <module>

AttributeError: 'Student' object has no attribute'set_age'

为了给所有实例都绑定方法,可以给class绑定方法:

>>> def set_score(self, score):

... self.score = score

...

>>> Student.set_score = MethodType(set_score,None, Student)

给class绑定方法后,所有实例均可调用:

>>> s.set_score(100)

>>> s.score

100

>>> s2.set_score(99)

>>> s2.score

99

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class能添加的属性:

>>> class Student(object):

__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

>>> s = Student() # 创建新的实例

>>> s.name = 'Michael' # 绑定属性'name'

>>> s.age = 25 # 绑定属性'age'

>>> s.score = 99 # 绑定属性'score'

Traceback (most recent call last):

File"<stdin>", line 1, in <module>

AttributeError: 'Student' object has no attribute'score'

由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。

使用__slots__要注意,__slots__定义的属性仅对当前类起作用,对继承的子类是不起作用的:

>>> class GraduateStudent(Student):

... pass

...

>>> g = GraduateStudent()

>>> g.score = 9999

除非在子类中也定义__slots__,这样,子类允许定义的属性就是自身的__slots__加上父类的__slots__。

Python学习 Day 8 继承 多态 Type isinstance dir __slots__的更多相关文章

  1. Python设计模式 - 基础 - 封装 & 继承 & 多态

    面向对象的核心是对象,世间万物都可以看作对象,任何一个对象都可以通过一系列属性和行为来描述,可以包含任意数量和类型的数据或操作.类是用来描述具有相同属性和方法的所有对象的集合.类通常是抽象化的概念,而 ...

  2. python oop常用术语 继承 多态 封装

    面向对象优点 1.通过封装明确了内外 2.通过继承+多态在语言层面支持了归一化设计 抽象/实现 抽象指对现实世界问题和实体的本质表现,行为和特征建模,建立一个相关的子集,可以用于 绘程序结构,从而实现 ...

  3. Python面向对象,析构继承多态

    析构: def __del__(self): print("del..run...") r1 = Role("xx") del r1 结果打印del..run. ...

  4. python学习笔记14(多态、封装、继承)

    创建自已的对象(尤其是类型或者被称为类的对象)是python非常核心的概念. 多态: 可对不同类的对象使用同样的操作. 封装:对外部世界隐藏对象的工作细节. 继承:以普通的类为基础建立专门的类对象. ...

  5. python学习日记(继承和多态)

    继承 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Base class.S ...

  6. python 面向对象五 获取对象信息 type isinstance getattr setattr hasattr

    一.type()函数 判断基本数据类型可以直接写int,str等: >>> class Animal(object): ... pass ... >>> type( ...

  7. Python学习之单继承与多继承

    继承 面向对象编程语言的一个主要功能就是“继承”. 继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展. (1) 单继承:python同时支持类的继承 ...

  8. python基础之组合继承多态

    组合 1.什么是组合 组合就是一个类的对象具备一个指向另外一个类的对象的属性 2.为何用组合 组合可以减少代码冗余 3.如何使用 class People: def __init__(self,nam ...

  9. python 面对对象 类(继承, 多态)

    继承,继承其它实例化样本的属性和方法,需要在声明里重新定义和使用 class School(object): def __init__(self, name, addr): self.name = n ...

随机推荐

  1. mysql备份及还原

    mysql怎样复制数据库?或者说,将数据库拷贝到另外一台机? 按照我的理解,复制数据库,如果是: 1.直接拷贝数据库文件,应该先停数据服务,否则拷不出来.但是,生产机器,哪能说停就停呢? 2.在线拷贝 ...

  2. Codeforces 768 E. Game of Stones 博弈DP

    E. Game of Stones   Sam has been teaching Jon the Game of Stones to sharpen his mind and help him de ...

  3. Hbase权限配置以及使用手册

    1.Hbase权限控制简介 Hbase的权限控制是通过AccessController Coprocessor协处理器框架实现的,可实现对用户的RWXCA的权限控制. 2.配置 配置hbase-sit ...

  4. 怎样快速刪除Word中超链接?

    有时我们从网上down了一些资料,存到Word文档里,会发现一些文字和图片带有超链接.这其实是Word自动修改功能引起的麻烦,那么,有什么办法可以把这些超链接快速批量删掉吗? 步骤/方法 1 按键盘上 ...

  5. BZOJ1016 &amp;&amp; JSOI2008] 最小生成树计数

    题目链接:id=1016">点击打开链接 裸题 #pragma comment(linker, "/STACK:1024000000,1024000000") #i ...

  6. mongo12---手动预先分片

    手动预先分片:(每个片上的数据是不一样的,是分开存,不是做备份) 自动分片有可能短期内某个片的数据过大,硬盘不够用了.能否100000-30000就到1号片. //以shop.user表为例,先声明s ...

  7. POJ3692 Kindergarten —— 二分图最大团

    题目链接:http://poj.org/problem?id=3692 Kindergarten Time Limit: 2000MS   Memory Limit: 65536K Total Sub ...

  8. android 改变状态栏(StatusBar)颜色

    public static void changeColor(Activity paramActivity, int paramInt1) { if (Build.VERSION.SDK_INT &g ...

  9. sql 指删除表,改表名,改字段名

    删除表: DECLARE @Table NVARCHAR(30) DECLARE tmpCur CURSOR FOR SELECT name FROM sys.objects WHERE TYPE=' ...

  10. 线程Coroutines 和 Yield(转)

    之前一直很纠结这个问题,在网上找到了这篇文章,给大家分享下: 第一种方法:    void Start()     {         print("Starting " + Ti ...