Python入门【​编辑、组合、设计模式_工厂模式实现 、设计模式_单例模式实现、工厂和单例模式结合、异常是什么?异常的解决思路 】(十七)

👏作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白
📕系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发
📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
🍂博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人

🔥🔥🔥 python入门到实战专栏:从入门到实战

🔥🔥🔥 Python爬虫开发专栏:从入门到实战

🔥🔥🔥 Python办公自动化专栏:从入门到实战

🔥🔥🔥 Python数据分析专栏:从入门到实战

🔥🔥🔥 Python前后端开发专栏:从入门到实战  

目录

​编辑

组合

设计模式_工厂模式实现 

设计模式_单例模式实现

工厂和单例模式结合

异常是什么?

异常的解决思路 


组合

结婚就是组合。两人组合后,可以复用对方的属性和方法! 

除了继承,“组合”也能实现代码的复用!“组合”核心是“将父类对象作为子类的属性”。

1、is-a 关系,我们可以使用“继承”。从而实现子类拥有的父类的方法和属性。 is-a 关系指的是类似这样的关系:狗是动物,dog is animal。狗类就应该继承动物类。

2、has-a 关系,我们可以使用“组合”,也能实现一个类拥有另一个类的方法和属性。 has-a 关系指的是这样的关系:手机拥有CPU。 MobilePhone has a CPU

#组合测试
class MobilePhone:
    def __init__(self,cpu,screen):
        self.cpu = cpu
        self.screen = screen
class CPU:
    def calculate(self):
        print("计算,算个12345")
class Screen:
    def show(self):
        print("显示一个好看的画面,亮瞎你的钛合金大眼")
c = CPU()
s = Screen()
m = MobilePhone(c,s)
m.cpu.calculate()       #通过组合,我们也能调用cpu对象的方法。相当于手机对象间接拥有了“cpu的方法”
m.screen.show()

 运算结果:

计算,算个12345

显示一个好看的画面,亮瞎你的钛合金大眼

设计模式_工厂模式实现 

设计模式是面向对象语言特有的内容,是我们在面临某一类问题时候固定的做法,设计模式有很多种,比较流行的是:GOF(Goup Of Four)23种设计模式。当然,我们没有必要全部学习,学习几 个常用的即可。 对于初学者,我们学习两个最常用的模式:工厂模式和单例模式。 工厂模式实现了创建者和调用者的分离,使用专门的工厂类将选择 实现类、创建对象进行统一的管理和控制。 

#工厂模式
class CarFactory:
    def createCar(self,brand):
        if brand == "奔驰":
            return Benz()
        elif brand == "宝马":
            return BMW()
        elif brand ==  '比亚迪':
            return BYD()
        else:
            return "未知品牌,无法创建"
class Benz:
    pass
class BMW:
    pass
class BYD:
    pass
factory = CarFactory()
c1 = factory.createCar("奔驰")
c2 = factory.createCar("宝马")
print(c1)
print(c2)

 运行结果:

<__main__.Benz object at 0x021C5770>
<__main__.BMW object at 0x021C5790>

设计模式_单例模式实现

单例模式(Singleton Pattern)的核心作用是确保一个类只有一个 实例,并且提供一个访问该实例的全局访问点。 单例模式只生成一个实例对象,减少了对系统资源的开销。当一个对象的产生需要比较多的资源,如读取配置文件、产生其他依赖对象时,可以产生一个“单例对象”,然后永久驻留内存中,从而极大 的降低开销。 

⚠️单例模式有多种实现的方式,我们这里推荐重写 __new__() 的方 法。

#单例模式
class MySingleton:
    __obj = None
    __init_flag = True
    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)
        return cls.__obj
    def __init__(self,name):
        if MySingleton.__init_flag:
            print("init....")
            self.name = name
            MySingleton.__init_flag = False
a = MySingleton("aa")
print(a)
b = MySingleton("bb")
print(b)

 运算结果:

init....
<__main__.MySingleton object at 0x01E15610>
<__main__.MySingleton object at 0x01E15610>

工厂和单例模式结合

设计模式称之为“模式”,就是一些固定的套路。我们很容易用到其他场景上,比如前面讲的工厂模式,我们需要将工厂类定义成“单例”,只需要简单的套用即可实现: 

#测试工厂模式和单例模式的整合使用
class CarFactory:
    __obj = None           #类属性
    __init_flag = True
    def create_car(self,brand):
        if brand =="奔驰":
            return Benz()
        elif brand =="宝马":
            return BMW()
        elif brand == "比亚迪":
            return BYD()
        else:
            return "未知品牌,无法创建"
    def __new__(cls, *args, **kwargs):
        if cls.__obj ==None:
            cls.__obj = object.__new__(cls)
        return cls.__obj
    def __init__(self):
        if CarFactory.__init_flag:
            print("init CarFactory....")
            CarFactory.__init_flag = False
class Benz:
    pass
class BMW:
    pass
class BYD:
    pass
factory = CarFactory()
c1 = factory.create_car("奔驰")
c2 = factory.create_car("比亚迪")
print(c1)
print(c2)
factory2 = CarFactory()
print(factory)
print(factory2)

运算结果:

init CarFactory....
<__main__.Benz object at 0x01E36E90>
<__main__.BYD object at 0x01E36C30>
<__main__.CarFactory object at 0x01E36730>
<__main__.CarFactory object at 0x01E36730>

1、 如下代码测试对象的浅拷贝、深拷贝,请绘制出内存示意图。

#测试对象的引用赋值、浅拷贝、深拷贝
import copy
class MobilePhone:
    def __init__(self,cpu,screen):
        self.cpu = cpu
        self.screen = screen
class CPU:
    def calculate(self):
        print("计算,算个12345")
        print("CPU对象:",self)
class Screen:
    def show(self):
        print("显示一个好看的画面,亮瞎你的钛合金大眼")
        print("屏幕对象:",self)
c = CPU()
s = Screen()
m = MobilePhone(c,s)
m.cpu.calculate()
n = m               #两个变量,但是指向了同一个对象
print(m,n)
m2 = copy.copy(m)   #m2是新拷贝的另一个手机对象
print(m,m2)
m.cpu.calculate()
m2.cpu.calculate()   #m2和m拥有了一样的cpu对象和screen对象
m3 = copy.deepcopy(m)
m3.cpu.calculate()      #m3和m拥有不一样的cpu对象和screen对象

2、定义发动机类Motor、底盘类Chassis、座椅类Seat,车辆外壳 类Shell,并使用组合关系定义汽车类。其他要求如下:

定义汽车的run()方法,里面需要调用Motor类的work()方法,也需要调用座椅类Seat的work()方法,也需要调用底盘类Chassis的work()方法

3 、使用工厂模式、单例模式实现如下需求:

(1) 电脑工厂类ComputerFactory用于生产电脑Computer。工厂类使用单例模式,也就是说只能有一个工厂对象。

(2) 工厂类中可以生产各种品牌的电脑:联想、华硕、神舟 

(3) 各种品牌的电脑使用继承实现:

(4) 父类是Computer类,定义了calculate方法

(5) 各品牌电脑类需要重写父类的calculate方法

4、 定义一个Employee雇员类,要求如下:

(1) 属性有:id、name、salary

(2) 运算符重载+:实现两个对象相加时,默认返回他们的薪水和

(3) 构造方法要求:输入name、salary,不输入id。id采用自增 的方式,从1000开始自增,第一个新增对象是1001,第二个新 增对象是1002。

(4) 根据salary属性,使用@property设置属性的get和set方法。 set方法要求输入:1000-50000范围的数字。

异常是什么?

软件程序在运行过程中,非常可能遇到刚刚提到的这些问题,我们称之为异常,英文是: Exception ,意思是例外。

遇到这些例外情况, 或者叫异常,我们怎么让写的程序做出合理的处理,安全的退出, 而不至于程序崩溃呢?我们本章就要讲解这些问题。 

工作中,程序遇到的情况不可能完美。比如:程序要打开某个文件,这个文件可能不存在或者文件格式不对;程序在运行着,但是内存或硬盘可能满了等等。

伪代码说明异常机制 

如果我们要拷贝一个文件,在没有异常机制的情况下,我们需要考虑各种异常情况,伪代码如下:

这种方式,有两个坏处:

1 逻辑代码和错误处理代码放一起!

2 程序员本身需要考虑的例外情况较复杂,对程序员本身要求较高!

如上情况,如果是用Python的异常机制来处理,对比如下: 

异常机制本质: 当程序出现异常,程序安全的退出、处理完后继续执行的机制 

python中,引进了很多用来描述和处理异常的类,称为异常类。异 常类定义中包含了该类异常的信息和对异常进行处理的方法。下面较为完整的展示了python中内建异常类的继承层次: 

我们处理一下,遇到的第一个异常:

#测试简单的0不能做除数异常

a = 3/0 

Traceback (most recent call last):
  File "...mypro_exception/my01.py", line 1,
in <module>
    a = 3/0
ZeroDivisionError: division by zero

Process finished with exit code 1

 python中一切都是对象,异常也采用对象的方式来处理。处理 过程:

1、抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给解释器。

2、 捕获异常:解释器得到该异常后,寻找相应的代码来处理该异常

异常的解决思路 

解决异常问题的态度

1 、学习完异常相关知识点,只是开始对异常有些认识,不意味着你会调试任何异常;

2、调试异常,需要大量的经验作为基础。因此,大家不要在此停留,继续往后学习。碰到每个异常, 都要花心思去解决而不要动不动张口问人。通过自己的努力无法解决,再去找老师同学帮助解决。

解决每一个遇到的异常,建议大家遵循如下三点:

1、 不慌张,细看信息,定位错误。看清楚报的错误信息,并定位发生错误的地方。

2 、百度并查看十个相关帖子。将异常类信息进行百度,至少查看十个以上的相关帖子。

3 、以上两步仍然无法解决,找老师和同学协助解决。

正常情况,自己遵循如上步骤解决30个以上的错误,就能积累初步的调试经验,以后遇到的大部分错误都能独立完成。

异常解决的关键:定位 

当发生异常时,解释器会报相关的错误信息,并会在控制台打印出 相关错误信息。我们只需按照从上到下的顺序即可追溯 (Trackback)错误发生的过程,最终定位引起错误的那一行代码。

【示例】追溯异常发生的过程

def a():
    print("run in a() start! ")
    num = 1/0
    print("run in a() end! ")
def b():
    print("run in b() start!")
    a()
    print("run in b() end! ")
def c():
    print("run in c() start!")
    b()
    print("run in c() end! ")
print("step1")
c()
print("step2")

控制台打印结果:

step1
run in c() start!
run in b() start!
run in a() start!
Traceback (most recent call last):
  File "...mypro_exception/my01.py", line 17, in <module>
    c()
  File "...mypro_exception/my01.py", line 12, in c
    b()
  File "...mypro_exception/my01.py", line 7,in b
    a()
  File "...mypro_exception/my01.py", line 3,in a
    num = 1/0
ZeroDivisionError: division by zero
Process finished with exit code 1

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值