IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python 之面向对象 -> 正文阅读

[Python知识库]Python 之面向对象

面向对象编Object Oriented Programming?简写?OOP

面向对象与面向过程对比

面向过程:

  • ? ? 注重 步骤与过程,不注重职责分工
  • ? ? 如果需求复杂,代码会变得很复杂
  • ? ? 开发复杂项目,没有固定的套路,开发难度很大!

面向对象:

  • ? ? 注重 对象和职责,不同的对象承担不同的职责
  • ? ? 更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路
  • ? ? 需要在面向过程基础上,再学习一些面向对象的语法

面向对象三大特性

  1. 封装?根据?职责?将?属性?和?方法?封装?到一个抽象的??中
    • 定义类的准则
  2. 继承?实现代码的重用,相同的代码不需要重复的编写
    • 设计类的技巧
    • 子类针对自己特有的需求,编写特定的代码
  3. 多态?不同的?子类对象?调用相同的?父类方法,产生不同的执行结果

    • 多态?可以?增加代码的灵活度
    • 以?继承?和?重写父类方法?为前提
    • 是调用方法的技巧,不会影响到类的内部设计

类和对象的概念?

?

?是对一群具有?相同 特征?或者?行为?的事物的一个统称,是抽象的,不能直接使用

  • 特征?被称为?属性
  • 行为?被称为?方法

在程序开发中,要设计一个类,通常需要满足一下三个要素:

  1. 类名?这类事物的名字,满足大驼峰命名法(每一个单词的首字母大写、单词与单词之间没有下划线
  2. 属性?这类事物具有什么样的特征
  3. 方法?这类事物具有什么样的行为

对象?

  • 对象?是?由类创建出来的一个具体存在,可以直接使用
  • 由?哪一个类?创建出来的?对象,就拥有在?哪一个类?中定义的属性、方法?

类和对象的关系

  • 类是模板对象?是根据??这个模板创建出来的,应该?先有类,再有对象
  • ?只有一个,而?对象?可以有很多个
    • 不同的对象?之间?属性?可能会各不相同
  • ?中定义了什么?属性和方法对象?中就有什么属性和方法,不可能多,也不可能少

面相对象基础语法

dir()?内置函数?

在?Python?中?对象几乎是无所不在的,我们之前学习的?变量数据函数?都是对象

使用内置函数?dir?传入?标识符?/?数据,可以查看对象内的?所有属性及方法

定义简单的类(只包含方法)

class 类名:

    def 方法1(self, 参数列表):
        pass

    def 方法2(self, 参数列表):
        pass
  • 方法?的定义格式和之前学习过的函数?几乎一样
  • 区别在于第一个参数必须是?self,大家暂时先记住,稍后介绍?self

创建对象

当一个类定义完成之后,要使用这个类来创建对象,语法格式如下??

对象变量 = 类名()
class Cat:
    """这是一个猫类"""

    def eat(self):
        print("小猫爱吃鱼")

    def drink(self):
        print("小猫在喝水")

tom = Cat()
tom.drink()
tom.eat()

方法中的?self?参数?

1、在类的外部给对象增加属性(简单,但不推荐)

在?类的外部的代码?中直接通过?.?设置一个属性即可

tom.name = "Tom"
...

lazy_cat.name = "大懒猫"

2、self?在方法内部输出属性?

  • 由?哪一个对象?调用的方法,方法内的?self?就是?哪一个对象的引用
  • 调用方法时,程序员不需要传递?self?参数
  • 在?类的外部,通过?变量名.?访问对象的?属性和方法
  • 在?类封装的方法中,通过?self.?访问对象的?属性和方法?
class Cat:

    def eat(self):
        print("%s 爱吃鱼" % self.name)

tom = Cat()
tom.name = "Tom"
tom.eat()

lazy_cat = Cat()
lazy_cat.name = "大懒猫"
lazy_cat.eat()

初始化方法?

  • 当使用?类名()?创建对象时,会?自动?执行以下操作:
    1. 为对象在内存中?分配空间?—— 创建对象
    2. 为对象的属性?设置初始值?—— 初始化方法(init)
  • 这个?初始化方法?就是?__init__?方法,__init__?是对象的内置方法
  • __init__?方法是?专门?用来定义一个类?具有哪些属性的方法!;该方法在创建对象时会被自动调用

1、在初始化方法内部定义属性?

  • 在?__init__?方法内部使用?self.属性名 = 属性的初始值?就可以?定义属性
  • 定义属性之后,再使用类创建的对象,都会拥有该属性
class Cat:

    def __init__(self):

        print("这是一个初始化方法")

        # 定义用 Cat 类创建的猫对象都有一个 name 的属性
        self.name = "Tom"

    def eat(self):
        print("%s 爱吃鱼" % self.name)

# 使用类名()创建对象的时候,会自动调用初始化方法 __init__
tom = Cat()

tom.eat()

2、初始化的同时设置初始值?

在开发中,如果在?创建对象的同时,就设置对象的属性,可以做以下操作:

  1. 把希望设置的属性值,定义成?__init__?方法的参数
  2. 在方法内部使用?self.属性 = 形参?接收外部传递的参数
  3. 在创建对象时,使用?类名(属性1, 属性2...)?调用
class Cat:

    def __init__(self, name):
        print("初始化方法 %s" % name)
        self.name = name
    ...

tom = Cat("Tom")
...

lazy_cat = Cat("大懒猫")
...

内置方法和属性?

?__del__?方法

  • 在?Python?中

    • 当使用?类名()?创建对象时,为对象?分配完空间后,自动?调用?__init__?方法
    • 当一个?对象被从内存中销毁?前,会?自动?调用?__del__?方法
  • 应用场景

    • __init__?改造初始化方法,可以让创建对象更加灵活
    • __del__?如果希望在对象被销毁前,再做一些事情,可以考虑一下?__del__?方法
  • 生命周期

    • 一个对象从调用?类名()?创建,生命周期开始
    • 一个对象的?__del__?方法一旦被调用,生命周期结束
    • 在对象的生命周期内,可以访问对象属性,或者让对象调用方法
class Cat:

    def __init__(self, new_name):

        self.name = new_name

        print("%s 来了" % self.name)

    def __del__(self):

        print("%s 去了" % self.name)

# tom 是一个全局变量
tom = Cat("Tom")
print(tom.name)

# del 关键字可以删除一个对象
del tom

print("-" * 50)

__str__?方法?

  • ?在?Python?中,使用?print?输出?对象变量,默认情况下,会输出这个变量?引用的对象?是?由哪一个类创建的对象,以及?在内存中的地址十六进制表示
  • 如果在开发中,希望使用?print?输出?对象变量?时,能够打印?自定义的内容,就可以利用?__str__?这个内置方法了

注意:__str__?方法必须返回一个字符串

class Cat:

    def __init__(self, new_name):

        self.name = new_name

        print("%s 来了" % self.name)

    def __del__(self):

        print("%s 去了" % self.name)

    def __str__(self):
        return "我是小猫:%s" % self.name

tom = Cat("Tom")
print(tom)

??封装?

  • 封装?是面向对象编程的一大特点
  • 面向对象编程的?第一步?—— 将?属性?和?方法?封装?到一个抽象的??中
  • 外界?使用??创建?对象,然后?让对象调用方法
  • 对象方法的细节?都被?封装?在?类的内部
  • 一个对象的?属性?可以是?另外一个类创建的对象

  • 在?对象的方法内部,是可以?直接访问对象的属性?的
  • 同一个类?创建的?多个对象?之间,属性?互不干扰!

定义没有初始值的属性

在定义属性时,如果?不知道设置什么初始值,可以设置为?None

  • None?关键字?表示?什么都没有
  • 表示一个?空对象没有方法和属性,是一个特殊的常量
  • 可以将?None?赋值给任何一个变量
class Soldier:

    def __init__(self, name):

        # 姓名
        self.name = name
        # 枪,士兵初始没有枪 None 关键字表示什么都没有
        self.gun = None

身份运算符

身份运算符用于?比较?两个对象的?内存地址?是否一致 ——?是否是对同一个对象的引用

  • 在?Python?中针对?None?比较时,建议使用?is?判断
运算符描述实例
isis 是判断两个标识符是不是引用同一个对象x is y,类似 id(x) == id(y)
is notis not 是判断两个标识符是不是引用不同对象x is not y,类似 id(a) != id(b)

is 与 == 区别:

is?用于判断?两个变量 引用对象是否为同一个?==?用于判断?引用变量的值?是否相等

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> b is a 
False
>>> b == a
True

??私有属性和私有方法

  • 在实际开发中,对象?的?某些属性或方法?可能只希望?在对象的内部被使用,而?不希望在外部被访问到
  • 私有属性?就是?对象?不希望公开的?属性
  • 私有方法?就是?对象?不希望公开的?方法

定义方式

在?定义属性或方法时,在?属性名或者方法名前?增加?两个下划线,定义的就是?私有?属性或方法

class Women:

    def __init__(self, name):

        self.name = name
        self.__age = 18

    def __secret(self):
        # 在对象的方法内部,是可以访问对象的私有属性的
        print("%s 的年龄是 %d" % (self.name, self.__age))


xiaofang = Women("小芳")

# 私有属性,在外界不能够被直接访问
# print(xiaofang.__age)
# 私有方法,同样不允许在外界直接访问
# xiaofang.__secret()

伪私有属性和私有方法(科普)?

Python?中,并没有?真正意义?的?私有

  • 在给?属性方法?命名时,实际是对?名称?做了一些特殊处理,使得外界无法访问到
  • 处理方式:在?名称?前面加上?_类名?=>?_类名__名称
# 私有属性,外部不能直接访问到
print(xiaofang._Women__age)

# 私有方法,外部不能直接调用
xiaofang._Women__secret()

继承?

继承的概念、语法和特点

继承的概念

子类?拥有?父类?的所有?方法?和?属性

?继承的语法

class 类名(父类名):

    pass
  • 子类?继承自?父类,可以直接?享受?父类中已经封装好的方法,不需要再次开发
  • 子类?中应该根据?职责,封装?子类特有的?属性和方法

继承的传递性

  • C?类从?B?类继承,B?类又从?A?类继承
  • 那么?C?类就具有?B?类和?A?类的所有属性和方法

子类?拥有?父类?以及?父类的父类?中封装的所有?属性?和?方法

方法的重写?

当?父类?的方法实现不能满足子类需求时,可以对方法进行?重写(override)

重写?父类方法有两种情况:

  1. 覆盖?父类的方法
  2. 对父类方法进行?扩展

1、覆盖父类的方法

如果在开发中,父类的方法实现?和?子类的方法实现完全不同,就可以使用?覆盖?的方式,在子类中?重新编写?父类的方法实现

  • 具体的实现方式,就相当于在?子类中?定义了一个?和父类同名的方法并且实现
  • 重写之后,在运行时,只会调用?子类中重写的方法,而不再会调用?父类封装的方法

2、对父类方法进行?扩展

如果在开发中,子类的方法实现?中?包含?父类的方法实现(父类原本封装的方法实现?是?子类方法的一部分),就可以使用?扩展?的方式

  1. 在子类中?重写?父类的方法
  2. 在需要的位置使用?super().父类方法?来调用父类方法的执行
  3. 代码其他的位置针对子类的需求,编写?子类特有的代码实现

1)关于?super

  • 在?Python?中?super?是一个?特殊的类
  • super()?就是使用?super?类创建出来的对象
  • 最常?使用的场景就是在?重写父类方法时,调用?在父类中封装的方法实现

2)调用父类方法的另外一种方式(知道)

在?Python 2.x?时,如果需要调用父类的方法,还可以使用以下方式:

父类名.方法(self)
  • 这种方式,目前在?Python 3.x?还支持这种方式

注:

  • 在开发时,父类名?和?super()?两种方式不要混用
  • 如果使用?当前子类名?调用方法,会形成递归调用,出现死循环
lass Animal:

    def eat(self):
        print("吃---")

    def drink(self):
        print("喝---")

    def run(self):
        print("跑---")

    def sleep(self):
        print("睡---")


class Dog(Animal):

    def bark(self):
        print("汪汪叫")


class XiaoTianQuan(Dog):

    def fly(self):
        print("我会飞")

    def bark(self):

        # 1. 针对子类特有的需求,编写代码
        print("神一样的叫唤...")

        # 2. 使用 super(). 调用原本在父类中封装的方法
        # super().bark()

        # 父类名.方法(self)
        Dog.bark(self)
        # 注意:如果使用子类调用方法,会出现递归调用 - 死循环!
        # XiaoTianQuan.bark(self)

        # 3. 增加其他子类的代码
        print("$%^*%^$%^#%$%")


xtq = XiaoTianQuan()

# 如果子类中,重写了父类的方法
# 在使用子类对象调用方法时,会调用子类中重写的方法
xtq.bark()

父类的 私有属性 和 私有方法

  1. 子类对象?不能?在自己的方法内部,直接?访问 父类的?私有属性?或?私有方法
  2. 子类对象?可以通过?父类?的?公有方法?间接?访问到?私有属性?或?私有方法
  • 私有属性、方法?是对象的隐私,不对外公开,外界?以及?子类?都不能直接访问
  • 私有属性、方法?通常用于做一些内部的事情
class A:

    def __init__(self):

        self.num1 = 100
        self.__num2 = 200

    def __test(self):
        print("私有方法 %d %d" % (self.num1, self.__num2))

    def test(self):
        print("父类的公有方法 %d" % self.__num2)

        self.__test()


class B(A):

    def demo(self):

        # 1. 在子类的对象方法中,不能访问父类的私有属性
        # print("访问父类的私有属性 %d" % self.__num2)

        # 2. 在子类的对象方法中,不能调用父类的私有方法
        # self.__test()

        # 3. 访问父类的公有属性
        print("子类方法 %d" % self.num1)

        # 4. 调用父类的公有方法
        self.test()
        pass

# 创建一个子类对象
b = B()
print(b)

b.demo()
# 在外界访问父类的公有属性/调用公有方法
# print(b.num1)
# b.test()

# 在外界不能直接访问对象的私有属性/调用私有方法
# print(b.__num2)
# b.__test()

多继承?

子类?可以拥有?多个父类,并且具有?所有父类?的?属性?和?方法

?语法:

class 子类名(父类名1, 父类名2...)
    pass
class A:

    def test(self):
        print("test 方法")


class B:

    def demo(self):
        print("demo 方法")


class C(A, B):
    """多继承可以让子类对象,同时具有多个父类的属性和方法"""
    pass


# 创建子类对象
c = C()

c.test()
c.demo()

:如果?父类之间?存在?同名的属性或者方法,应该?尽量避免?使用多继承?

Python 中的 MRO —— 方法搜索顺序??

  • Python?中针对??提供了一个?内置属性?__mro__?可以查看?方法?搜索顺序
  • MRO 是?method resolution order,主要用于?在多继承时判断 方法、属性 的调用 路径
print(C.__mro__)

输出结果

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
  • 在搜索方法时,是按照?__mro__?的输出结果?从左至右?的顺序查找的
  • 如果在当前类中?找到方法,就直接执行,不再搜索
  • 如果?没有找到,就查找下一个类?中是否有对应的方法,如果找到,就直接执行,不再搜索
  • 如果找到最后一个类,还没有找到方法,程序报错

新式类与旧式(经典)类

object?是?Python为所有对象提供的?基类,提供有一些内置的属性和方法,可以使用?dir?函数查看

  • 新式类:以?object?为基类的类,推荐使用
  • 经典类:不以?object?为基类的类,不推荐使用

  • 在?Python 3.x?中定义类时,如果没有指定父类,会?默认使用?object?作为该类的?基类?——?Python 3.x?中定义的类都是?新式类

  • 在?Python 2.x?中定义类时,如果没有指定父类,则不会以?object?作为?基类?

新式类?和?经典类?在多继承时 ——?会影响到方法的搜索顺序;为了保证编写的代码能够同时在?Python 2.x?和?Python 3.x?运行! 今后在定义类时,如果没有父类,建议统一继承自?object

class 类名(object):
    pass

多态?

多态?不同的?子类对象?调用相同的?父类方法,产生不同的执行结果

  • 多态?可以?增加代码的灵活度
  • 以?继承?和?重写父类方法?为前提
  • 是调用方法的技巧,不会影响到类的内部设计

多态?更容易编写出出通用的代码,做出通用的编程,以适应需求的不断变化!

class Dog(object):

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

    def game(self):
        print("%s 蹦蹦跳跳的玩耍..." % self.name)


class XiaoTianDog(Dog):

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

        # 让狗玩耍
        dog.game()


# 1. 创建一个狗对象
# wangcai = Dog("旺财")
wangcai = XiaoTianDog("飞天旺财")

# 2. 创建一个小明对象
xiaoming = Person("小明")

# 3. 让小明调用和狗玩的方法
xiaoming.game_with_dog(wangcai)

?

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-10-16 19:36:13  更:2021-10-16 19:37:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 19:37:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码