Python面向对象篇--封装、继承、多态、类属性、类方法、静态方法、单例模式

封装

在Python代码中,封装有两层含义:

  1. 把现实世界中的主体中的属性和方法书写到类的里面的操作即为封装

    class Person():
        # 封装属性
        # 封装方法
    
  2. 封装可以为属性和方法添加为私有权限

封装中的私有属性和私有方法

在面向对象代码中,我们可以把属性和方法分为两大类:公有(属性、方法)、私有(属性、方法)

公有属性和公有方法:无论在类的内部还是在类的外部我们都可以对属性和方法进行操作。

但是有些情况下,我们不希望在类的外部对类内部的属性和方法进行操作。我们就可以把这个属性或方法封装成私有形式。

设置私有属性和私有方法的方式非常简单:在属性名和方法名 前面 加上两个下划线 __ 即可。

class Person():
    def __init__(self, name):
        self.name = name
        self.__age = 1000
    def __show(self):
        print(self.__age)

p1 = Person("ii")
p1.__show() # AttributeError: 'Person' object has no attribute '__show'
print(p1.__age) # AttributeError: 'Person' object has no attribute '__age'

那么我们如何在外部调用到私有成员:

class Person():
    def __init__(self, name):
        self.name = name
        self.__age = 1000
    def __show(self):
        print(self.__age)

    def getAge(self):
        return self.__age

    def getShow(self):
        self.__show()

p1 = Person("ii")
print(p1.getAge())
p1.getShow()

在这里插入图片描述

继承

class Person():
    def __show(self):
        print(123)

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

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

class Teather(Person):
    pass

t1 = Teather()
t1.eat()
t1.run()
# t1.__show() # AttributeError: 'Teather' object has no attribute '__show'

单继承

一个类只能继承自一个其他的类,不能继承多个类。这个类会有具有父类的属性和方法。

单继承特性:传递性

class A():
    def show(self):
        print("hello")

class B(A):
    pass

class C(B):
    pass

c = C()
c.show()

在这里插入图片描述

注意

  1. 在Python中,类理论上是不区分大小写的。但是要遵循一定的命名规范:首字母必须是字母或下划线,其中可以包含字母、数字和下划线,而且要求其命名方式采用大驼峰。

  2. 在Python面向对象代码中,建议在编写父类时,让其自动继承object类。但是其实不写也可以,因为默认情况下,Python中的所有类都继承自object。

多继承

虽然多继承允许我们同时继承自多个类,但是实际开发中,应尽量避免使用多继承,因为如果两个类中出现了相同的属性和方法就会产生命名冲突。

class A():
    def show(self):
        print("hello")

class B():
    pass

class C(A, B):
    pass

子类扩展:重写父类属性和方法

重写也叫作覆盖,就是当子类成员与父类成员名字相同的时候,从父类继承下来的成员会重新定义。

思考:

重写父类中的call方法以后,此时父类中的call方法还在不在?

答:还在,只不过是在其子类中找不到了。类方法的调用顺序,当我们在子类中重构父类的方法后,Cat子类的实例先会在自己的类 Cat 中查找该方法,当找不到该方法时才会去父类 Animal 中查找对应的方法。

class A():
    def show(self):
        print("A")

class B(A):
    def show(self):
        print("B")

a = A()
a.show()

b = B()
b.show()

在这里插入图片描述

super()调用父类属性和方法

super():调用父类属性或方法,完整写法:super(当前类名, self).属性或方法(),在Python3以后版本中,调用父类的属性和方法我们只需要使用super().属性或super().方法名()就可以完成调用了。

class A():
    def show(self):
        print(123);

class B(A):
    def showB(self):
        super(B, self).show()

a = A()
a.show()

在这里插入图片描述

MRO属性或MRO方法:方法解析顺序

MRO(Method Resolution Order):方法解析顺序,我们可以通过类名.__mro__返回元组类型)或类名.mro()返回元组类型)获得“类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找到。

class A():
    pass

class B(A):
    pass

class C(B):
    pass

print(C.__mro__)
print(C.mro())

在这里插入图片描述

多态

多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果。

  1. 多态依赖继承

  2. 子类方法必须要重写父类方法

实现

多态:可以基于继承也可以不基于继承,因为即使涉及到的几个类没有继承关系,但是每个类都是继承自object

class A():
    def show(self):
        print("A")

class B():
    def show(self):
        print("B")

def run(obj):
    obj.show()

run(A())
run(B())

在这里插入图片描述

面向对象其他特性

类属性

Python中,属性可以分为实例属性和类属性。

类属性就是类对象中定义的属性,它被该类的所有实例对象所共有。通常用来记录与这类相关的特征,类属性不会用于记录具体对象的特征。

在Python中,一切皆对象。类也是一个特殊的对象,我们可以单独为类定义属性。

定义:

class Person():
    age = 0

实例:

class A():
    cnt = 0
    def __init__(self):
        A.cnt += 1

a1 = A()
a2 = A()
a3 = A()

print(f"共存在{A.cnt}个实例")

在这里插入图片描述

类方法

为什么需要类方法,在面向对象中,特别强调数据封装性。所以不建议直接在类的外部对属性进行直接设置和获取。所以我们如果想操作类属性,建议使用类方法。

class A():
    cnt = 0
    def __init__(self):
        A.cnt += 1
    @classmethod
    def getCnt(cls):
        return cls.cnt

a1 = A()
a2 = A()
a3 = A()

print(f"共存在{A.getCnt()}个实例")

在这里插入图片描述

类方法主要用于操作类属性或类中的其他方法。

静态方法

在开发时,如果需要在类中封装一个方法,这个方法:

  1. 既不需要访问实例属性或者调用实例方法

  2. 也不需要访问类属性或者调用类方法

这个时候,可以把这个方法封装成一个静态方法

# 开发一款游戏
class Game(object):
    # 开始游戏,打印游戏功能菜单
    @staticmethod
    def menu():
        print('1、开始游戏')
        print('2、游戏暂停')
        print('3、退出游戏')

# 开始游戏、打印菜单
Game.menu()

在这里插入图片描述

单例模式

单例模式属于单例模式。

设计模式就是前人根据实际的问题提出的问题解决方案,我们把这种就称之为设计模式。

在实际的运用中,存在一些类,只需要实例化一个对象,就可以完成其所有的功能操作。所以,如果我们能够通过某些技巧,使得一个类只能开辟一个对象空间的话,这样就可以节省相应的对象资源,这种模式就叫作单例模式

使用类名()创建对象时,Python的解释器首先会调用__new__方法为对象分配空间。

__new__方法

__new__是一个由object积累提供的内置的静态方法,主要作用有两个:

  1. 在内存中为对象分配空间

  2. 返回对象的引用

Python解析器获得对象的引用后,将引用作为第一个参数,传递给__init__方法重写__new__方法的代码非常固定,一定要使用return super().__new__(cls),否则Python解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法。

__new__方法是一个静态方法,在调用时,要求将自身类信息cls作为参数传递到这个方法中,这个方法属于object类中的一个静态方法。

class A():
    def __new__(cls, *args, **kwargs):
        print("__new__")
        return super().__new__(cls)

a = A()
print(a)

在这里插入图片描述

注:类属性在内存中是一个特殊的存在,其不用于以前讲过的局部变量(局部变量当函数执行完毕后,其会被内存所销毁)。但是类属性一旦定义,除非对象以及这个类在内存中被销毁了,否则其不会自动销毁。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FeatherWaves

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值