python面向对象开发基础篇

48
Python面向对象开发基础篇 [email protected] 2013/04/04

Upload: modou-li

Post on 19-Jul-2015

1.030 views

Category:

Documents


15 download

TRANSCRIPT

Page 1: Python面向对象开发基础篇

Python面向对象开发基础篇

[email protected]

2013/04/04

Page 2: Python面向对象开发基础篇

编程范式

• 过程:模式、数据结构、过程

• 对象:封装了状态和方法,在对象间通过

传递消息

• 函数:函数、闭包、递归等

• Python是多范式的编程语言

Page 3: Python面向对象开发基础篇

什么是面向对象

Page 4: Python面向对象开发基础篇

基于分类的思考方法

Window

MessageBox

Dialog Widget

Panel Button

抽象

具体

Page 5: Python面向对象开发基础篇

Class

class

subclassderive, inherit

定义了功能模板,是一

类事物的集合,是抽象

概念

Page 6: Python面向对象开发基础篇

Window

widthheight

backgroundcolorfont

draw()fresh()

destroy()move()resize()

名称

属性

方法

类的组成

• public

• private

• protect

Page 7: Python面向对象开发基础篇

instance = class()

一个类可以创建多个实例,每个实例可

以拥有不同的属性值

class 杯子

玻璃杯 = 杯子(材料=玻璃)红色金属杯 = 杯子(材料=金属,颜色=红

色)

Page 8: Python面向对象开发基础篇

面向对象的三大特点

封装

继承

多态

Page 9: Python面向对象开发基础篇

封装

继承

多态

数据+方法

子类可以使用父类

的属性和方法

同一个父类可以派

生出不同的子类

覆盖 改变父类的属性值和方法实现

Page 10: Python面向对象开发基础篇

为什么需要面向对象

封装

重用 分解

Page 11: Python面向对象开发基础篇

什么时候使用面向对象

在需要的时候使用

Page 12: Python面向对象开发基础篇

Python的面向对象

Page 13: Python面向对象开发基础篇

import osclass Command(object):

def __init__(self, name):self.name = name

def __call__(self, *args, **kwargs):raise NotImplementedError

class DirCommand(Command):def __call__(self, dir):

os.system('dir %s' % dir)

dir_cmd = DirCommand('dir')dir_cmd('.')

Page 14: Python面向对象开发基础篇

• 使用class来定义类

• Python的类可以从父类继承,支持多个父类

• 类中可以保存属性和方法

• 属性可以是descriptor,通常的数据类型

• 特殊的方法,如:私有方法(开始有两个

下划线),特殊方法(前后各有两个下划线)

• __init__ 为初始化方法,一般不讲构造方

法,不是必须的

Page 15: Python面向对象开发基础篇

• obj = Class(*args, **kwargs) => obj = Class().__init__(*args, **kwargs)

• obj.attr 可以访问类中定义的属性

• obj.func()可以调用类中定义的方法

• 属性可以在运行时动态绑定

Page 16: Python面向对象开发基础篇

建议使用类和实例来描述,以避

免与对象的说法冲突。

一切皆对象--数据及功能的结合

Page 17: Python面向对象开发基础篇

old style class和new style class

>>> class A:pass

>>> type(A)

<type ‘classobj’>

>>> type(int)

<type ‘type’>

>>> class A1(object):pass

>>> type(A1)

<type ‘type’>

Page 18: Python面向对象开发基础篇

new style class的作用

• 在Python 2.2之前,类与类型是不统一的

• 在Python 2.2实现了统一

• 让内置的类型子类化更方便

• 提供了属性(property)的机制

• 实现了static和class方法

• 提供了metaclass编程

Unifying types and classes in Python 2.2PEP-252: Making types look more like classesPEP-253: Subtyping built-in types

Page 19: Python面向对象开发基础篇

class A(object):passclass B(A):

“””B description”””def out_b(self, name):

print nameclass C(A):

def out_c(self, name):print name

class D(B, C):pass

>>> d = D()>>> d.out_b('hello')hello

Page 20: Python面向对象开发基础篇

• 一个类可以有一个或多个基类,多个基类之间使用’,’分隔

• 类下可以定义doc_string

• 如果不存在基类,则为一个old-style类

• 只有当所有基类都是old-style类时,子类才是old-style类,否则就是new-style类

• 如果不需要基类,则可以把object作为基类来创建new-style类

• 在3.x将不存在old-style类,所有的类都是new-style,所以可以省略object

Page 21: Python面向对象开发基础篇

• 在类上定义的属性将在所有实例间共享

class C(object):count = 0

c1 = C()c2 = C()C.count += 1print c1.count, c2.count

1, 1

Page 22: Python面向对象开发基础篇

class C(object):

x = 20

def call(self):

C.x += 2

print C.x

print self.__class__

C.y = 21

• 在方法中通过 类 变量来使用类属性

• 属性可以动态绑定到类或实例变量上

Page 23: Python面向对象开发基础篇

类的自省

• isinstance() 判断一个实例是否属性某个类>>> isinstance(c1, C)True

• issubclass() 判断一个类是否是另一个类的子类>>> issubclass(D, D)True>>> issubclass(D, C)True

Page 24: Python面向对象开发基础篇

• dir(D) 可以列出类的属性名,包括方法

• D.__name__ 可以得到类的名称

>>> D.__name__‘D’

• D.__module__ 得到类所在的模块

• D.__bases__ 得到所有基类

>>> D.__bases__(<class '__main__.B'>, <class '__main__.C'>)

Page 25: Python面向对象开发基础篇

如何判断一个对象是类

考虑使用types,它定义了许多类型,但是:

>>> import types

>>> class A:pass

>>> isinstance(A, types.ClassType)

True

>>> isinstance(A, types.TypeType)

False

>>> import types

>>> class B(object):pass

>>> isinstance(B, types.ClassType)

False

>>> isinstance(B, types.TypeType)

True

Page 26: Python面向对象开发基础篇

>>> import inspect

>>> inspect.isclass(A)

True

>>> inspect.isclass(B)

True

Page 27: Python面向对象开发基础篇

类私有属性

• 以两个下划线开始的属性,python会把它编译为:_classname__attribute

• 其实python中不存在真正的私有属性• 更多是采用约定的方式,如以’_’开始的

>>> class C5(object):... __private = 23>>> print C5.__privateAttributeError: class A has no attribute ' private'>>> print C5. _C5__private23

Page 28: Python面向对象开发基础篇

static和class方法

>>> class A(object):... @staticmethod... def static():... print A.__name__... @classmethod... def method(cls):... print cls.__name__>>> a = A()>>> a.static()‘A’>>> A.static()‘A’>>> a.method()‘A’>>> A.method()‘A’

Page 29: Python面向对象开发基础篇

• 静态方法:类相当于只是起到一个作用域

限制的作用,可以通过实例,类来访问

• 类方法:第一个参数是类对象,可以通过

实例,类来访问。与实例无关的方法可以定义为类方法。

• 实例方法:第一个参数是实例对象,只能

通过实例来访问。

Page 30: Python面向对象开发基础篇

为什么实例的第一个参数是self

• 约定俗成

• 类方法第一个参数是 cls

• 实例方法第一个参数是 self

• 用其它的名字也可以

Page 31: Python面向对象开发基础篇

>>> d = D()>>> isinstance(d, D)True>>> class E(object):... def __init__ (self, n):... self.x = n>>> e = E(42)>>> print e.x42>>> e.z = 8>>> print e.z8

• 创建一个实例,只要象写调用一

个函数一样调用类对象。

• 如果类定义了__init__方法,则创

建实例时会把参数传给它来执

行。

• 可以动态向实例绑定新的属性

创建实例

Page 32: Python面向对象开发基础篇

动态处理属性

• getattr(obj, name, default=None)

• hasattr(obj, name)

• setattr(obj, name, value)

Page 33: Python面向对象开发基础篇

问题?Python如何获得一个属性

class A(object):

name = ‘A’

def __init__(self, name):

self.name = name

a = A(‘Hello’)

a.name, self.name, A.name的结果分别是什么?

Page 34: Python面向对象开发基础篇

MRO(Method Resolution Order)

• 先查找实例的属性(self.__dict__)

• 再在实例的类中查找(self.__class__.__dict__)

• 再到基类中查找

• 如果存在多个基类,根据mro的顺序

>>> D.mro()

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]

Page 35: Python面向对象开发基础篇

实例的自省

• isinstance() 判断一个实例是否属性某个类

>>> isinstance(c1, C)True

• self.__class__ 得到某实例的类对象

Page 36: Python面向对象开发基础篇

关于覆盖

• 在Python的类中,不允许存在多个同名的方

法,所以无法实现象java那样的方法重定义

• 只能通过可变参数(*args, **kwargs)或不同的名字来实现

Page 37: Python面向对象开发基础篇

如何调用父类的方法

class A(object):def __init__(self):

print 'A'class B(A):

def __init__(self):super(B, self).__init__()print 'B'

b = B()

Page 38: Python面向对象开发基础篇

特殊类方法

• 如果方法名前后各有两个下划线,一般为

特殊的类方法。

• 特殊的类方法有一些是系统已经定义好的,

有特殊的命名要求

• 特殊的类可以实现特殊的语法效果

Page 39: Python面向对象开发基础篇

__init__

• 实现一个实例的初始化

Page 40: Python面向对象开发基础篇

__str__, __repr__, __unicode__

• 可让一个对象通过print来打印

• print一个对象时,一般先找__str__,再找__repr__。

• 如果在运算中存在unicode处理,会尝试调

用__unicode__来进行转換

Page 41: Python面向对象开发基础篇

__call__

• 可以用来模拟函数调用

class A(object):

def __call__(self, name)

print name

a = A()

print a(‘hello’)

Page 42: Python面向对象开发基础篇

__lt__, __le__, __eq__, __ne__, __gt__, __ge__

• 用来模拟数学比较

Page 43: Python面向对象开发基础篇

__getattr__, __setattr_, __delattr__

• 用来摸拟属性操作

Page 44: Python面向对象开发基础篇

__getitem__, __setitem__, __delitem__

• 用来模拟字典操作

Page 46: Python面向对象开发基础篇

什么时候使用面向对象

• 简化代码,实现封装

• 当遇到可以进行抽象的场合,如:GUI控件开发

• 在实现可扩展机制的时候,如:配置文件读取,实现不同的配置文件格式的解析

• 以类的定义形式来实现某种简化的定义,如:ORM, Form等

• 利用类的特殊方法来实现类函数的闭包调用

Page 47: Python面向对象开发基础篇

什么时候不使用面向对象

• 简单情况

• 过程化编程,如:算法

• 不适合的地方

• 。。。

Page 48: Python面向对象开发基础篇

更高级的内容?

• descriptor

• property

• metaclass