面向对象

面向对象1

面向过程和面向对象概念
  • 面向过程:根据业务逻辑从上到下写代码(每一步都自己去实现)
  • 面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程(不用具体到每一步,会调用就行。面向对象是基于面向过程的)
    面向对象有三种特性:1.封装  2.继承  3.多态
    

C语言和C++语言都是编译过后才能生成(.exe)可执行程序后才可运行。
python语言是直接运行,直到运行到出错地方才停止

一、 类和对象

A、 类

类的概念

类是抽象的,在使用的时候通常会找到这个类的一个具体的存在,使用这个具体的存在。一个类可以找到多个对象

B、 对象

对象的概念

某一个具体事物的存在,在现实世界中可以是看得见摸得着的。

C、 类和对象之间的关系

类就是创建对象的模板

二、 __init__() 方法

方法类似于C++中的成员函数

  • __init__() 方法,在创建一个对象时默认被调用,不需要手动调用,与C++中的构造函数类似
  • __init__(self) 中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么 __init__(self) 中除了self作为第一个形参外还需要2个形参,例如 __init__(self, x, y)
  • __init__(self) 中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去

三、 str() 方法


  • 在 python 中方法名如果是 (__xxx__()) ,那么就有特殊的功能,因此叫做"魔法"方法
  • 当使用print输出对象的时候,只要自己定义了 (__str__(self)) 方法,那么就会打印从在这个方法中 return 的数据。

四、 self


  • 可以把 self 当做C++中类里面的this指针一样理解,就是对象本身的意思
  • 某个对象调用其方法是,python 解释器会把这个对象作为第一个参数传递给 self ,所以开发者只需要传递后面的参数即可。

五、 隐藏数据

修改对象属性(数据)有两种办法

A、 直接通过对象名修改

B、 通过方法间接修改

应用题:老王开枪
class Human:
    def __init__(self, name):
        self.name = name
        self.blood = 100
        self.gun = None

    def __str__(self):
        return self.name + "剩余血量为:" +  str(self.blood)

    def install_ball(self, clip, ball):
        clip.reserve_ball(ball)

    def install_clip(self, gun, clip):
        gun.link_clip(clip)

    def with_gun(self, gun):
        self.gun = gun

    def shoot(self, rob):
        self.gun.shoot(rob)

    def injured(self, hurt):
        self.blood -= hurt

class Ball:
    def __init__(self, hurt):
        self.hurt_l = hurt

    def hurt(self, rob):
        rob.injured(self.hurt_l)

class Clip:
    def __init__(self, capacity):
        self.capacity = capacity
        self.capacity_list = []

    def __str__(self):
        return "弹夹里面的数量为:" + str(len(self.capacity_list)) + "/" + str(self.capacity)

    def reserve_ball(self, ball):
        if len(self.capacity_list) < self.capacity:
            self.capacity_list.append(ball)

    def balls(self):
        # 判断当前弹夹中是否还有子弹
        if len(self.capacity_list) > 0:
            ball = self.capacity_list[-1]
            self.capacity_list.pop()
            return ball
        else:
            return None

class Gun:
    def __init__(self):
        self.clip = None

    def __str__(self):
        if self.clip:
            return "枪里面装有弹夹"
        else:
            return "枪里面没有弹夹"
    def link_clip(self, clip):
        if not self.clip:
            self.clip = clip

    def shoot(self, rob):
        ball = self.clip.balls()
        if ball:
            ball.hurt(rob)
        else:
            print("没有子弹了...")

# 创建一个人对象
laowang = Human("laowang")
print(laowang)

# 创建一个弹夹
clip = Clip(20)
print(clip)

# 装子弹
i=0
while i<5:
    ball = Ball(5)
    laowang.install_ball(clip, ball)
    i += 1

# 打印子弹个数
print(clip)

# 创建一个枪对象
gun = Gun()
print(gun)

# 把弹夹装进枪里面
laowang.install_clip(gun, clip)
print(gun)

# 创建一个敌人
rob = Human("rob")
print(rob)

laowang.with_gun(gun)

laowang.shoot(rob)
print(rob)
print(clip)

面向对象2

一、 保护对象的属性

如果有一个对象,当需要对其进行修改属性时,有两种方法
  • 对象名.属性名 = 数据 ----->直接修改
  • 对象名.方法名() ----->间接修改
为了更好的保护属性安全,即不能随意修改,一般处理方式为
  • 将属性定义为私有属性,然后添加一个可以调用的方法提供调用

  • python 中没有像C++中public和private这些关键字来区别公有属性和私有属性
  • 它是以属性命名方式来区分,如果在属性名前面加了2个下划线,则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加2个下划线的话表示该方法是私有的)

注意:如果直接使用( print(laowang.__age)会报错 ),可直接修改虽然不会报错,但是这个值不会被真正的写入

二、 __del__() 方法

  • 创建对象后,python解释器默认调用 __init__() 方法; 当删除一个对象时,python解释器也会默认调用一个方法,这个方法为 __del__() 方法



注意:当使用 del 删除变量指向的对象时,如果对象的引用计数不为1,那么此时只会让这个引用计数减1,只有当这个引用计数器变为1时再次调用del,此时才会把对象进行删除

三、 继承

  • 子类在继承的时候,在定义时,小括号中为父类的名字
    注意:私有的属性、方法,不会被子类继承,也不能被访问

四、 重写父类方法与调用父类方法

所谓重写,就是子类中有一个和父类相同名字的方法,在子类中方法会覆盖掉父类中同名的方法


五、 多态

概念:定义时的类型和运行时的类型不一样,此时就成为了多态(同一条执行语句,不同的执行结果)



注意1: 与 C 和 C++ 这些强类型语言不同的是,而python这类弱类型语言不用指定传入的参数类型,只要各类中含有被调用的方法,就能被执行
注意2: 多态必须得重写

补充:

若类中有一个方法为 __test() 的私有方法, 那么我们可以如何访问呢?

六、 类属性和实例属性

  • 实例属性: 也叫对象属性,归对象管理
  • 类属性: 它被类和对象所共有,和 C++ 中的静态成员变量类似。对于共有的类属性可以通过类或者对象直接访问



注意1:当实例属性和类属性名相同时,用对象访问的属性将是实例属性(有实例属性就以实例属性为主,没有就访问类属性)

问:既然能够通过对象名获取类属性的值,那能不能通过对象名向类属性修改呢?

注意2:类属性的值不能通过对象名进行修改,如果修改本质是创建了一个和类属性同名的实例属性

七、 类方法和静态方法

概念:1.类方法需要用修饰器(@classmethod) 来标识其为类方法,第一个参数必须是类,一般以cls作为第一个参数。2.静态方法需要通过修饰器(@staticmethod)来进行修饰,静态方法不需要定义参数


  • 1.实例方法:用于修改实例属性
  • 2.类方法:用于修改类属性
  • 3.静态方法:用于打印菜单等工作

面向对象3

一、 工厂模式


二、 __new__ 方法

注意:在 (__init__)初始化之前还有一个 (__new__) 对象的创建,并且必须要有返回值

三、 单例模式

就是一个类只能创建出一个对象

四、 异常

概念:当 python 检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是异常(意料之中的错误)。

A、 捕获异常



注意:当 try 内部出现异常后,后面的语句将不会被执行

B、 捕获多个异常


注意:当捕获多个异常时,可以把要捕获的异常的名字放在 except 后,并使用元组的方式进行存储

C、获取异常的信息描述



result 存储异常的基本信息

D、 捕获所有异常

1 捕获所有异常


2 捕获所有异常并存储异常信息


E、 else


注意:如果未出现异常才执行else的语句,如果try里面出现的异常没有被捕获则执行系统默认的异常

F、 finally

概念:在程序中,如果一个代码必须要执行,即无论是否产生异常都要执行,那么此时就需要使用finally。


G、异常的传递


H、 抛出自定义的异常

概念:可以用 raise 语句来引发一个异常。异常对象必须有一个名字,并且是 Exception 类的子类。


I、 异常处理中抛出异常


五、 模块

概念:python 中的模块就是一个py文件中整体的代码,与C语言的头文件类似

A、 模块的制作

概念:在 python 中每个python文件都可以作为一个模块,模块的名字就是文件名字。

自己定义的test模块

在main中调用test模块中的函数

运行结果:

注意:当使用 (import test) 的时候,会执行 test.py 中的所有函数。等价于直接执行 (python3 test.py)

解决方案:使用 (__name__) 变量。若直接执行 (python3 test.py) 时,(__name__)变量值为(__main__), 若在 main.py 文件中含有 (import test) 时,(__name__)变量值为(test)

自己定义的test模块

main.py中的代码不变

运行结果:

B、 import

在 python 中用关键字 import 来引入某个模块。比如要要引用模块 math ,就可以在文件最开始的地方用 import math 来引入

    引入模块:import module1, module2 ...
    调用函数:module1.函数名


C、 form...import

从模块中导入一个指定的部分到当前的命名空间中,不仅可以引入函数,还可以引入一些全局变量、类等。

    格式:from fbi import fbifuction   导入fbi模块的fbifuction的函数到当前命名空间


注意:通过这种方式引入的时候,如果两个模块中的含有相同名称函数的时候,后面一次引用会覆盖前一次引入。

D、 from...import *

把一个模块的所有内容全部导入到当前的命名空间

    格式:from module import *

E、 定位模块

  • 当导入一个模块,python解释器对模块位置的搜索顺序是:
  1. 当前目录
  2. python搜索在 shell 变量PATH下的每个目录
    可以使用:echo $PATH
  3. python 会查看默认路径, /usr/local/lib/python/
    在交互模式下使用os模块
  4. 模块搜索路径存储在 sys 模块的 sys.path 变量中。变量包含当前目录。
    在交互模式下使用sys模块的path

例:当被调用的模块文件和执行文件不在同一个目录下,如何调用自定义模块
/work/practice/python/008_module/TEST目录下的 test.py

/work/practice/python/008_module目录下的 001_main.py

执行结果:

F、 __pycache__

__pycache__ 里面存储的是缓存文件,即为了效率会把编译好的内容存放在 __pycache__ 目录下的 (.pyc)文件中。根据时间戳来决定被 import 后的文件是否被编译
注意:只要 import 就有编译缓存

G、 __all__

注意:__all__只对 * 有效。 当没有 __all__ 的时候 使用 (from module import *) 会把模块中的函数都导入;当有 __all__时,只导入all里边的函数。----->用列表的方式赋值

test.py 中的内容:

main.py 中的内容:

执行结果:

六、 Python 中的包

包的概念:将有联系的模块组织在一起,即放在同一个文件夹下,并且在这个文件夹下创建一个名字为 __init__.py 文件,那么这个文件夹就称为包。

A、 使用(import 文件.模块) 的方式导入

B、 使用(from 文件夹 import 模块) 的方式导入

解决方法:在 msg 文件夹下创建 __init__.py 文件,并在文件中写入如下内容

__init__ 文件内容:

再次执行:

注意: __init__.py 的作用:控制导入的模块

七、 给程序传参数



例:通过传入的参数来执行不同的函数

八、 列表推导式

所谓的列表推导式,就是轻量级循环创建列表。

A、 基本的方法

B、 再循环过程中使用if

C、 2个for循环

本质:双重for循环,用元组保存

D、 3个for循环

本质:三重for循环

九、 set(集合)、list(列表)、tuple(元组)

注意:set(集合) 中没有重复

set、list、tuple之间的相互转换


作用:使用 set ,可以快速的完成对列表或者元组中的元素去重复的功能。

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

原文地址:https://www.cnblogs.com/luosir520/p/11446420.html