赞
踩
面向对象的三大特征:封装,继承,多态
封装:根据职责将属性和方法封装到一个抽象的类中
继承:实现代码的重用,相同的代码不需要重复的编写
多态:(以封装和继承为前提)不同的子类调用相同的方法,产生不同的结果
eg :对于人类
程序员和设计师对于work则为不同
实例1:
class Dog(object):
def __init__(self,name):
self.name = name
def game(self):
print '%s 蹦蹦跳跳的玩耍...' %self.name
class Xiaotianquan(Dog):
# 父类方法不能满足子类的需求的时候,重写game方法
def game(self):
print '%s 飞到天上玩...' %self.name
class Person(object):
def __init__(self,name):
self.name = name
def game_with_dog(self,dog):
print '%s 和 %s 快乐的玩耍' %(self.name,dog.name)
1).创建一个狗对象
wangcai = Dog('旺财')
wangcai = Xiaotianquan('飞天神狗')
2).创建一个小明对象(小明是一个人)
xiaoming = Person('小明')
3).让小明和狗玩
xiaoming.game_with_dog(wangcai)
注意:Person类中只需让狗对象调用game方法(),而不需要关心具体
是什么狗,game方法是在Dog父类中定义的
在程序执行时,传入不同的狗对象的实参,就会产生不同的执行效果
(1)类是一个特殊的对象---类对象
在程序运行时,类对象在内存中只有一份,通过他可以创建出很多个对象实例
除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法
(2)类属性:就是给类对象定义的属性
类属性不会用于记录具体的对象特征
使用赋值语句在class关键字下方可以定义类属性
lass Tool(object):
# 1.使用赋值语句定义类属性,记录所有的工具数量
count = 0
def __init__(self,name):
self.name = name
# 让类属性的值 +1
Tool.count += 1
# 创建工具对象(对象在创建的时候,会自动调用初始化方法)
tool1 = Tool('斧头')
tool2 = Tool('榔头')
tool3 = Tool('水桶')
print Tool.count
(3)类方法:就是针对类对象定义的方法,在类方法内部就 可以直接访问类属性或调用类
class Toy(object):
# 使用赋值语句定义类属性,记录所有玩具的数量
count = 0
@classmethod
def show_toy_count(cls):
# 在类方法的内部,可以直接访问类属性或调用类方法
print '玩具对象的数量 %d' % cls.count
def __init__(self,name):
self.name = name
Toy.count += 1
# 创建玩具对象
toy1 = Toy('乐高')
toy2 = Toy('玩具车')
# 调用类方法
Toy.show_toy_count()
在开发的时候,如果需要在类中封装一个方法,这个方法
既不需要访问实例属性或者调用实例方法
也不需要访问那类属性或者调用类方法
这个时候可以把这个方法封装成一个静态方法
class Cat(object):
@staticmethod
# 不访问实例属性/类属性
# 静态方法不需要传递第一个参数self
def call():
print '喵喵~'
# 通过类名. 调用静态方法
# 不需要创建对象,就可以直接调用
Cat.call()
1).使用面向对象开发,第一步是设计类
2).使用 类名() 创建对象,创建对象的动作有两步
1.在内存中为对象分配空间
2.调用初始化方法__init___ 为对象初始化
3).对象创建后,内存中就有了一个对象的实实在在的存在--实例
因此:
1.创建出来的对象叫做类的实例
2.创建对象的动作叫做实例化
3.对象的属性叫做实例属性
4.对象调用的方法叫做实例方法
在程序执行时:
1.对象各自拥有自己的实例属性
2.调用对象的方法,可以通过self
访问自己的属性
调用自己的方法
结论:
1).每一个对象都有自己独立的内存空间,保存各自不同的属性
2).多个对象的方法,在内存中之有一份,在调用方法时,需要把对象的引用传递到方法内 部
eg:综合案例
1.设计一个Game类
2.属性
定义一个类属性top_score记录游戏的历史最高分(与这个类有关,每次游戏与历史 最高分没关系)
定义一个实例属性player_name记录当前游戏玩家的玩家姓名
3.方法:
show_help显示游戏帮助信息(静态方法:既不需要访问类属性,也不需要访问实例 属性)
show_top_score显示历史最高分(类方法)
start_game开始当前玩家的游戏(实例方法)
class Game(object):
# 1.历史最高分
top_score = 0
def __init__(self, player_name):
self.player_name = player_name
@staticmethod
def show_help():
print '帮助信息:#!#!#!'
@classmethod
def show_top_score(cls):
print '历史记录 %d' % cls.top_score
def start_game(self):
print '%s 开始游戏啦' % self.player_name
1).查看游戏的帮助信息
Game.show_help()
2).查看历史最高分
Game.show_top_score()
3).创建游戏对象,开始游戏
game = Game('小明')
game.start_game()
1.实例方法--方法内部需要访问实例属性
实例方法内部可以使用 类名. 访问类属性
2.类方法:方法内部“只”需要访问类属性
3.静态方法:方法内部,不需要访问实例属性和类属性
如果方法内部 即需要访问实例属性,又需要访问类属性,应该定义什么方法?
实例方法
设计模式是前人工作的总结和提炼,通常,被人们广泛流传的设计模式就是针对
某一个问题的特定解决方案,使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码的可靠性
我们创建对象的时候,python解释器会帮我们做两件事:
__new__方法为对象分配空间
__init__(初始化方法)负责给对象初始化
注释:
(1)__new__是一个由object基类提供的内置的静态方法,主要有两个作用:
在内存中为对象分配空间
返回对象的引用
(2)我们要重写new方法,使用类名()创建对象的时候,返回的都是同一个地址
重写__new__方法的代码非常固定:
继承自父类方法
返回父类方法调用_new__方法的结果
重写__new__方法一定要return object.__new__(cls)
否则python的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法
eg:
class MusicPlsyer(object):
instance = None
def __new__(cls, *args, **kwargs):
#第一个参数cls:哪一个类调用就传递哪一个类
#第二个参数*args:多值的元组参数
#第三个参数**kwargs:多值的字典参数
#1.创建对象的时候,new方法会被自动调用
#print '创建对象,分配空间' # 重写了父类的方法
# 2.为对象分配空间
# 注意:__new__方法是一个静态方法,在调用的时候,第一个参数为cls
if cls.instance is None:
# 调用父类的方法,为第一个对象分配空间
cls.instance = object.__new__(cls)
# 3.返回对象的引用
return cls.instance
def __init__(self):
print '初始化播放器'
# 创建播放器对象
player1 = MusicPlsyer()
print player1
player2 = MusicPlsyer()
print player2
注释:观察在__new__中的print '创建对象,分配空间'实为重写了父类方法
在每次使用 类名() 创建对象时,python的解释器都会自动调用两个方法
__new__ 分配空间
__init__ 对象初始化
但在上一小结中 __new__方法改造之后,每次都会得到第一次被创建对象的引用
但是:初始化方法还会被再次掉用
解决办法:
1.定义一个类属性init_flag标记是否执行过初始化动作,初始值为false
2.在__init__方法中,判断init_flag,如果为false就执行初始化动作
3.然后将init_flag设置为trun
4.这样,再次自动调用__init__方法时,初始化动作就不会再次被执行了
class MusicPlayer(object):
instance = None
init_flag = False
def __new__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = object.__new__(cls)
return cls.instance
def __init__(self):
# 1.判断是否执行过初始化动作
if MusicPlayer.init_flag:
return
# 2.如果没有执行过,再执行初始化动作
print '初始化方法'
MusicPlayer.init_flag = True
player1 = MusicPlayer()
print player1
player2 = MusicPlayer()
print player2
(1)面对的问题
程序在运行的时候,如果python解释器遇到一个错误,会停止程序,并提示一些错误信息
这就是异常
例如:
In [3]: num = int(raw_input('请输入整数:'))
请输入整数:a
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-c670c150c028> in <module>()
----> 1 num = int(raw_input('请输入整数:'))
ValueError: invalid literal for int() with base 10: 'a'
(2)解决办法:
try:
尝试执行的代码
except:
出现错误的处理
如果希望程序无论出现任何错误,都不会因为python解释器抛出异常而终止,可以再增加一个except,语法如下:
except Exception as result(一个变量名 可以随便写):
print ('未知错误 %s' % result)
对比:图一
图二:
具体说明:
简单的捕获异常语法一个
在程序开发中,如果对某些代码的执行不能确定
(程序的语法完全正确)是否正确
(例如:提示用户输入一个整数,程序的能否正确执行,完全取决于用户的输入)
可以增加try来捕获异常
错误类型的捕获
在程序执行时,可能会遇到不同类型的异常,
并且需要针对不同类型的异常,
做不同的响应,这个时候,就需要捕获错误类型了
捕获未知错误:
在开发时,要预判到所有可能出现的错误,还是有一定的难度的
如果希望程序无论出现任何错误,都不会因为python解释器抛出异常而终止,可以再增加一个except
语法如下:
except Exception as result(一个变量名 可以随便写):
print ('未知错误 %s' % result)
(3)例如:
try:
# 不能确定正确执行的代码
num = int(raw_input('请输入一个整数:'))
except:
# 错误的处理
print '请输入正确的整数'
print '*' * 50
典例:
1.提示用户输入一个整数
2.使用8除以用户输入的整数并且输出
try:
num = int(raw_input('请输入一个整数:'))
result = 8 / num
print result
except ZeroDivisionError:
print '0不能做除数'
except ValueError:
print '请输入正确的整数'
except Exception as result:
print '未知错误 %s' % result
finally:
print '无论是否出现错误都会执行的代码'
print '*' * 50
(4)抛出异常
(1)抛出raise异常
应用场景
在开发中,除了代码执行出错python解释器会抛出异常之外
还可以根据应用程序特有的业务需求主动抛出异常
(2)抛出异常
python中提供了一个Exception异常类
在开发时,如果满足特定的业务需求时,希望抛出异常,可以:
1.创建一个Exception的对象
2.使用raise关键字抛出异常对象
典例:
需求:
提示用户输入密码,如果长度小于8位,就抛出异常
def input_password():
# 1.提示用户输入密码
pwd = raw_input('请输入密码:')
# 2.判断密码的长度 >=8,就返回用户输入的密码
if len(pwd) >= 8:
return pwd
# 3.如果<8,就主动抛出异常
print '抛出异常'
# 1.创建异常对象
ex = Exception('密码长度不够')
raise ex
# 注意:只抛出异常而不捕获异常,代码会报错
try:
print input_password()
except Exception as result:
print result
# 先创建异常对象,再抛出异常,再在主函数中捕获异常
可以理解为提前预言,让人更好的知道错误的原因
def func(num, div):
assert (div != 0),'div不能等于0'
return num / div
print func(10, 0)
对比
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。