第七章 Python面向对象

一、面向对象

  • 命名规则:python中,包名,模块名均小写;类名每个单词首字母大写;方法名除首个单词小写外其他单词首写字母大写。

  • 面向对象的三大特征:封装、继承、多态。

1、类和对象

  • 类:是一类具有相同属性和方法的对象的集合。
  • 对象:实例化即可得到一个具体的对象,这个对象就可以调用类的属性和方法。
  • 类的组成

    (1)类名 (给这多个事物起一个名字, 在代码中 满足大驼峰命名法(每个单词的首字母大写)) 。
    (2)属性 (事物的特征, 即有什么, 一般文字中的名词) 。
    (3) 方法 (事物的行为, 即做什么事, 一般是动词)。

  • 类的抽象(类的设计)

    类的抽象,其实就是找到 类的 类名, 属性 和方法

2、属性

  • 属性:对象的属性特征。
  • 属性的划分:实例属性和类属性。
2.1 实例属性

概念: 是实例对象 具有的属性

  • 定义和使用

    在 init 方法中, 使用 self.属性名 = 属性值 定义
    在方法中是 使用 self.属性名 来获取(调用)

  • 内存

    实例属性,在每个实例中 都存在一份。

  • 使用时机

    (1)基本上 99% 都是实例属性,即通过 self 去定义。
    (2)找多个对象,来判断这个值是不是都是一样的, 如果都是一样的, 同时变化,则一般定义为 类属性, 否则定义为 实例属性。

2.2 类属性

概念: 是 类对象 具有的属性。

  • 定义和使用

    在类内部,方法外部,直接定义的变量 ,就是类属性。
    使用: 类对象.属性名 = 属性值 or 类名.属性名 = 属性值
    类对象.属性名 or 类名.属性名

  • 内存

    只有 类对象 中存在一份

3、方法

  • 方法:对象所具有的能力动作。
  • 方法划分:实例方法、类方法和静态方法。
3.1 实例方法(最常用)
  • 定义

    在类中直接定义的方法 就是 实例方法。

class Demo:
    def func(self):   # 参数一般写作 self,表示的是实例对象
        pass
  • 定义时机(什么时候用)

    如果在方法中需要使用实例属性(即需要使用 self), 则这个方法必须定义为 实例方法 。

  • 调用

对象.方法名()   # 不需要给 self 传参
3.2 类方法(会用)
  • 定义
在方法名字的上方书写 @classmethod 装饰器(使用 @classmethod 装饰的方法)
class Demo:
    @classmethod
    def func(cls):  # 参数一般写作 cls, 表示的是类对象(即类名) class
        pass 
  • 定义时机(什么时候用)

    前提, 方法中不需要使用 实例属性(即 self)
    用到了类属性, 可以将这个方法定义为类方法,(也可以定义为实例方法)

  • 调用

# 1. 通过类对象调用
类名.方法名()  # 也不需要给 cls 传参, python 解释器自动传递
# 2. 通过实例对象调用
实例.方法名()  # 也不需要给 cls 传参, python 解释器自动传递
3.3 静态方法(基本不用)
  • 定义
#在方法名字的上方书写 @staticmethod 装饰器(使用 @staticmethod 装饰的方法)
class Demo:
    @staticmethod
    def func():   # 一般没有参数
        pass 
  • 定义时机(什么时候用)

    前提, 方法中不需要使用 实例属性(即 self)
    也不使用 类属性, 可以将这个方法定义为 静态方法

  • 调用

# 1. 通过类对象调用
类名.方法名() 
# 2. 通过实例对象调用
实例.方法名()  

4、魔法方法

python 中有一类方法, 以两个下划线开头,两个下划线结尾,并且在满足某个条件的情况下, 会自动调用, 这类方法称为 魔法方法。

4.1__init__ 方法 (构造方法)

init 方法, 创建对象之后,会自动调用 (构造方法)

  • 什么情况下自动调用

    创建对象之后会自动调用。

  • 有什么用, 用在哪

    (1) 给对象添加属性的, (初始化方法, 构造方法) 。
    (2) 某些代码, 在每次创建对象之后, 都要执行,就可以将这行代码写在 init 方法。

  • 书写的注意事项

    (1)不要写错了。
    (2)如果 init 方法中,存在出了 self 之外的参数, 在创建对象的时候必须传参。

class Cat:
    # 定义添加属性的方法
    def __init__(self, name, age):  # 这个方法是创建对象之后调用
        self.name = name  # 给对象添加 name 属性
        self.age = age   # 给对象添加 age 属性# 输出属性信息
    def show_info(self):
        print(f'小猫的名字是: {self.name}, 年龄是: {self.age}')
​
​
# 创建对象,不要在自己类缩进中创建
# Cat()  # 创建对象 ,会输出
blue_cat = Cat('蓝猫', 2)
​
blue = blue_cat
blue.show_info()# 创建黑猫
black_cat = Cat('黑猫', 3)
black_cat.show_info()
4.2__str__ 方法
  • 什么情况下自动调用

    使用 print(对象) 打印对象的时候 会自动调用。

  • 有什么用, 用在哪

    在这个方法中一般书写对象的 属性信息的, 即打印对象的时候想要查看什么信息,在这个方法中进行定义的。
    如果类中没有定义 str 方法, print(对象) ,默认输出对象的引用地址。

  • 书写的注意事项

    这个方法必须返回 一个字符串。

class Cat:
    # 定义添加属性的方法
    def __init__(self, n, age):  # 这个方法是创建对象之后调用
        self.name = n  # 给对象添加 name 属性
        self.age = age   # 给对象添加 age 属性def __str__(self):
        # 方法必须返回一个字符串, 只要是字符串就行,
        return f'小猫的名字是: {self.name}, 年龄是: {self.age}'
​
​
# 创建对象,不要在自己类缩进中创建
# Cat()  # 创建对象 ,会输出
blue_cat = Cat('蓝猫', 2)
print(blue_cat)# 创建黑猫
black_cat = Cat('黑猫', 3)
print(black_cat)

4.3__del__ 方法 (析构方法)

del 方法, 对象被删除销毁时, 自动调用的(遗言, 处理后事) (析构方法)

  • ​ 调用场景

    (1)程序代码运行结束, 所有对象都被销毁。

    (2)直接使用 del 删除对象(如果对象有多个名字(多个对象引用一个对象),需要吧所有的对象都删除才行 )。

class Demo:
    def __init__(self, name):
        print('我是 __init__, 我被调用了 ')
        self.name = name
​
    def __del__(self):
        print(f'{self.name} 没了, 给他处理后事...')
​
​
# Demo('a')
​
a = Demo('a')
​
b = Demo('b')
del a  # 删除销毁 对象,
print('代码运行结束')

二、封装

1、封装定义

概念:将数据和操作封装为一个有机的整体,由于类中私有成员都是隐藏的,只向外部提供有限的接口,所以能保证内部的高内聚性与外部的低耦合性。使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员,能顾增强安全性和简化编程。

class Person:#定义类,类名为Person
    name = 'zhangsan'#类的属性
    age = 18
    def study(self):#类的方法
        print('study')
    def sleep(self):
        print('sleep')
if __name__ == '__main__':
    p = Person()#实例化类得到一个对象p
    print(p.name)#调用类的属性,对象.属性
    p.study()#调用类的方法

2、私有化

私有化:私有化只有属性和方法,在类的外部将不能访问,只能在类的内部访问

class Person:#定义类,类名为Person
    name = 'zhangsan'#类的属性
    __age = 18
    def study(self):#类的方法
        print('study')
        print(self.name)
        print(self.__age)
        self.__sleep()#调用私有化方法
    def __sleep(self):
        print('sleep')
if __name__ == '__main__':
    # p = Person()#实例化类得到一个对象p
    # print(p.name)#调用类的属性,对象.属性
    # p.study()#调用类的方法
    print(Person().name)
    Person().study()

注意:
(1)私有化属性,名称前加两个下划线。
(2) 私有化方法,名称前加两个下划线。
(3)调用私有化属性,类的内部无论私有化或非私有化的属性和方法,想住在类的内部的其它方法中调用的话,必须使用关键字self

三、继承

什么是继承?答:至少基于两个类之间才有继承。

  • 概念:继承性更符合认知规律,使程序更易于理解,同时节省不必要的重复代码。类与类之间才能继承。

  • 继承子类:派生类/衍生类;继承父类:基类/超类,子类可以继承父类的属性和方法。

class Father:#父亲类
    name = "大张"
    def eat(self):
        print('Father:eat!')
class Son(Father):#儿子类(继承父亲类)
    name1 = "小张"
    def eat(self):
        print('Son:eat!')
if __name__ == '__main__':
    s = Son()
    s.eat()
    print(s.name)

继承调用规则:从左到右,先深度(纵向)再广度(横向)。

通俗讲:比如说要用钱,子类先看自己有没有,有的话就用自己的;如果没有找自己父亲要,父亲没有找自己的爷爷要,爷爷要是没有的话找i自己的妈妈要。

继承可以避免重复造轮子。如果父类当中的方法子类都要使用,推荐使用继承;如果子类中只是使用父类的部分方法,不推荐使用继承,建议使用导包。

  • 多继承
class GrandFather:#爷爷类
    name = "老张"
    def eat(self):
        print('GrandFather:eat!')
class Father(GrandFather):#父亲类(继承爷爷类)
    name = "大张"
    def eat(self):
        print('Father:eat!')
class Mother:#母亲类
    name = "李姐"
    def eat1(self):
        print('Mother:eat!')
class Son(Mother,Father):#多继承,儿子类(继承父亲类,母亲类)
    name = "小张"
    def eat1(self):
        print('Son:eat!')
if __name__ == '__main__':
    s =Son()
    print(s.name)
    s.eat()#鼠标点到方法调用的名称上,按ctrl+b可以直接跳到方法定义的地方,在方法定义的地方同样方式可以调回方法调用的地方
  • 如何在子类当中调用父类方法

子类当中调用父类同名方法使用关键子super()

  • 方式一:推荐,不管子类当中有误父类同名的方法,都会始终调用父类方法。
    super().study()

  • 方式二:不推荐,因为子类当中如果有同名的方法,将会优先调用自己的;如果没有的话,采用调用父类的方法。
    self.study()

class Father():#定义类方法一
class Father:
    def study(self):
        print('Father:study!')
class Son(Father):
    def study(self):#重写:父类方法不能满足子类需求,在子类当中重新定义同名的父类方法叫做重写
        print('Son:study!')
    def sleep(self):
        print('Son:sleep!')
        super().study()#方式一
        self.study()#方式二
if __name__ == '__main__':
    s = Son()
    s.sleep()

四、多态

多态:使用相同名称的方法,传入不同的对象,展现处不同的结果。

class Father:
    def study(self):
        print('Father:study!')
class Son:
    def study(self):
        print('Son:study!')
if __name__ == '__main__':
    def study(obj):
        obj.study()
    f =Father()
    s = Son()
    study(f)
    study(s)

1、重写

重写: 在子类中定义了和父类中名字相同的方法, 就是重写。

  • 重写的原因

    父类中的方法,不能满足子类对象的需求,所以重写。

  • 重写之后的特点:

    调用子类字节的方法, 不再调用父类中的方法。

  • 重写的方式:

    (1)覆盖(父类中功能完全抛弃,不要,重写书写)
    (2)扩展(父类中功能还调用,只是添加一些新的功能) (使用较多)

2、覆盖

(1)直接在子类中 定义和父类中名字相同的方法。
(2)直接在方法中书写新的代码。

3、扩展父类中的功能

(1)直接在子类中 定义和父类中名字相同的方法。
(2) 在合适的地方调用 父类中方法 super().方法()。
(3)书写添加的新功能。

class Dog:
    def bark(self):
        print('汪汪汪叫.....')
        print('汪汪汪叫.....')
​
​
class XTQ(Dog):
    # XTQ 类bark 方法不再是汪汪汪叫, 改为
    # 1. 先 嗷嗷嗷叫(新功能) 2, 汪汪汪叫(父类中功能)  3. 嗷嗷嗷叫 (新功能)
    def bark(self):
        print('嗷嗷嗷叫...')
        # 调用父类中的代码
        super().bark()  # print() 如果父类中代码有多行呢?
        print('嗷嗷嗷叫...')
​
​
xtq = XTQ()
xtq.bark()

4、重载

重载:Python没有重载,Java中有重载。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值