Python-16-面向对象_补充

面向对向-补充

一、面向对象的三大特征

  • 封装
    • 将事物的属性和方法写入到类中
    • 可以定义私有属性和方法
    • 实例空间保存实例属性,其余的属性和所有方法保存在类空间
  • 继承
    • 每个类都有至少一个父类,子类继承父类后,那么子类就拥有父类中所有的属性和方法
    • 子类不能继承私有属性和方法
  • 多态
    • 在方法中传入不同的对象,会产生不同的结果

二、多态

2.1 多态的概念

多态指的是事物的多种形态。

多态的前提是继承。

步骤:

  1. 定义一个父类,并且创建父类中相应的公共方法
  2. 定义多个子类,重写这个公共方法
  3. 将子类的实例传入到某个对象中,产生不同的形态(结果)

2.2 代码实现

背景:

  • UNIX是最早的通用操作系统,通用表示系统的可移植性高

  • 类UNIX:根据UNIX操作系统的开发规范开发的仿制品,比如:LinuxmacOS(FreeBSD)

# 定义一个UNIX类
class MyUnix(object):
    def work(self):
        print('UNIX可以玩游戏')

# 定义一个Linux类
class MyLinux(MyUnix):
    def work(self):
        print('Linux可以作为服务器')

# 定义一个macOS类
class MyMac(MyUnix):
    def work(self):
        print('mac可以做设计和编程')

# 定义一个用户类
class User(object):
    def use_os_work(self, os_obj):
        os_obj.work()


# 实例化两个操作系统子类
linux1 = MyLinux()
mac1 = MyMac()

# 实例化两个用户
user1 = User()
user2 = User()

# 让用户使用两个操作系统
user1.user_os_work(linux1)			# Linux可以作为服务器
User.use_os_work(user2, mac1)		# mac可以做设计和编程

三、类属性和实例属性

类属性是定义在类中并且在方法外的属性,它保存在类空间中;

一般类属性定义为变量,直接指向一个对象

3.1 类属性

3.1.1 定义和访问类属性

类属性保存在类空间,类属性被类对象和实例对象访问

class MyLinux(object):
    # 定义类属性,属性表示Linux的内核版本
    kernel_version = 5
	
    # 定义实例方法,初始化不同的Linux发行版
    def __init__(self, distro):
        self.distro = distro

# 通过类对象来访问
print(MyLinux.kernel_version)

# 实例化两个不同的Linux发行版
centos8 = MyLinux('CentOS8')
ubuntu20 = MyLinux('Ubuntu20')

# 通过实例对象来访问类属性
print(centos8.kernel_version)			# 5
print(ubuntu20.kernel_version)			# 5

定义类属性,只在类空间创建,如果定义实例属性,会在多个实例空间创建,缺点是占用内存资源

3.1.2 修改类属性

类属性只能通过类对象修改;

实例对象修改类属性,相当于创建一个实例属性

class MyLinux(object):
    kernel_version = 5

# 1. 通过类对象修改类属性,可以修改
MyLinux.kernel_version = 3
print(MyLinux.kernel_version)           # 3

# 实例化两个对象
centos8 = MyLinux()
ubuntu20 = MyLinux()

# 2.通过实例对象修改类属性
centos8.kernel_version = 4				# 相当于创建一个实例属性
print(centos8.kernel_version)           # 4。

print(ubuntu20.kernel_version)          # 3
  • 实例对象不能修改类属性;
  • 实例对象访问属性时,先在自身空间中查找,如果有则访问成功,否则访问类空间,类空间也没有则报错。

3.2 实例属性

实例属性保存在实例空间;

类对象不能访问实例属性

class MyLinux(object):
    def __init__(self):
        self.distro = 20

ubuntu1 = MyLinux()
# 1.1 通过实例对象访问实例属性
print(ubuntu1.distro)			# 20

# 1.2 通过类对象访问实例属性
print(MyLinux.distro)			# 报错

# 2.1 实例对象修改实例属性
ubuntu1.distro = 18
print(ubuntu1.distro)           # 18
  • 实例属性只能通过实例对象访问;

  • 多个实例对象不能相互访问

四、类方法和静态方法

4.1 类方法

  • 类方法的第一个形参必须为类对象的引用,一般使用cls
  • 类方法必须使用装饰器@classmethod来修饰类方法
class MyLinux(object):
    kernel = 5

    # 定义类方法
    @classmethod
    def get_kernel(cls):
        print(f'版本为{cls.kernel}')  # 在类方法中访问类属性
        print(f'{MyLinux.kernel}')

    # 定义实例方法
    def get_kernel_instance(self):
        print(f'版本为{self.kernel}')      # 在实例方法中使用 self.类属性 可以访问成功


# 实例化一个对象
ubuntu1 = MyLinux()

# 对象调用实例方法,OK
ubuntu1.get_kernel_instance()       # 版本为5

# 实例对象调用类方法,OK
ubuntu1.get_kernel()                # 可以在类的外部,可以通过实例对象访问类方法

# # 类对象调用类方法,OK
MyLinux.get_kernel()				# 版本为5

类方法的使用:

一般要在方法中操作类属性,那么就定义一个类方法;

4.2 静态方法

静态方法一般不传入cls或者self

静态方法需要使用@staticmethod来修饰

class MyLinux(object):
    # 定义静态方法,打印我是Linux发行的说明书
    @staticmethod
    def get_info():
        print('Linux发行的说明书')

    @classmethod
    def get_static(cls):
        cls.get_info()

    def get_static_instance(self):
        self.get_info()

# 1. 通过类对象调用
MyLinux.get_info()					# Linux发行的说明书
MyLinux.get_static()				# Linux发行的说明书

# 2. 通过实例对象来调用
centos1 = MyLinux()
centos1.get_info()					# Linux发行的说明书
centos1.get_static_instance()		# Linux发行的说明书

静态方法可以使用类对象或者实例对象来调用;

在类的内部,可以使用cls或者self来调用静态方法

静态方法一般用来作为实例对象的公共方法。

五、单例设计模式

无论实例化多少次,只创建一个内存空间

5.1 对象的实例过程

  • __new__:为实例对象创建一个内存空间,并将内存地址返回给CPython解释器
  • __init__:解释器在已创建的内存空间中添加实例属性

5.2 单例设计模式的原理

  • 重写__new__方法,如果没有创建内存空间则创建;如果已经创建空间,则不创建;
  • 定义__init__方法,如果没有初始化则进行初始化;如果已经初始化,则不初始化。

5.3 代码实现

class Student(object):
    # 创建一个类属性,表示内存的空间
    mem_space = None            # 假设没有创建实例空间,None表示没有实例空间
    ins_ = False            # 没有进行属性的添加

    def __new__(cls, *args, **kwargs):
        if not cls.mem_space:       # 如果没有创建实例空间,则创建
            cls.mem_space = super().__new__(cls)
        return cls.mem_space

    def __init__(self):
        if not Student.ins_:
            # 如果没有初始化实例,则初始化,并将类属性修改为True
            Student.ins_ = True
            print('这个是init方法')


s1 = Student()
s2 = Student()
s3 = Student()
print(s1)
print(s2)
print(s3)

''' 输出结果:
这个是init方法
<__main__.Student object at 0x000001D7E0F47310>
<__main__.Student object at 0x000001D7E0F47310>
<__main__.Student object at 0x000001D7E0F47310>
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值