python-多态

1,多态概念:

面向对象的三大特征:封装,继承,多态
封装:根据职责将属性和方法封装到一个抽象的类中
继承:实现代码的重用,相同的代码不需要重复的编写
多态:(以封装和继承为前提)不同的子类调用相同的方法,产生不同的结果
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父类中定义的
在程序执行时,传入不同的狗对象的实参,就会产生不同的执行效果

2,类属性and类方法

(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()

 

3,静态方法

在开发的时候,如果需要在类中封装一个方法,这个方法
    既不需要访问实例属性或者调用实例方法
    也不需要访问那类属性或者调用类方法
    这个时候可以把这个方法封装成一个静态方法
class Cat(object):
    @staticmethod
    # 不访问实例属性/类属性
    # 静态方法不需要传递第一个参数self
    def call():
        print '喵喵~'

# 通过类名. 调用静态方法
# 不需要创建对象,就可以直接调用
Cat.call()

4,类的结构说明

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()

5,区分各类方法

1.实例方法--方法内部需要访问实例属性
    实例方法内部可以使用 类名. 访问类属性
2.类方法:方法内部“只”需要访问类属性
3.静态方法:方法内部,不需要访问实例属性和类属性

如果方法内部 即需要访问实例属性,又需要访问类属性,应该定义什么方法?
实例方法

6,单例模式

1)基础了解:

设计模式是前人工作的总结和提炼,通常,被人们广泛流传的设计模式就是针对
某一个问题的特定解决方案,使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码的可靠性
我们创建对象的时候,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 '创建对象,分配空间'实为重写了父类方法

2)需求:让初始化方法只执行一次

在每次使用 类名() 创建对象时,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

7,文件异常

(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

# 先创建异常对象,再抛出异常,再在主函数中捕获异常


8,断言

可以理解为提前预言,让人更好的知道错误的原因
def func(num, div):
    assert (div != 0),'div不能等于0'
    return num / div
print func(10, 0)

对比

9,异常的传递

 

  • 7
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值