13 面向对象2:init和new、单例模式、property属性、魔术方法

1. init和new


# 1. __init__ 和 __new__ 魔术方法

# init: 构造函数(初始化或赋值操作),
# 创建(实例化)对象时被调用
# class A:
#     def __init__(self):
#         self.name = 'jiuge'  # 实例属性
#
# # 实例化对象
# a = A()
# print(a.name)  # 对象查看实例属性
# print(A.name)  # 类名不能查看实例属性


# 2.__new__ 方法 :创建这个实例对象的方法
# 作用:
#     1>在内存中为对象分配空间
#     2>返回对象的引用

# 继承中子类扩展父类的方法:重写

# class B:  # 先执行new方法,再执行init方法
#     def __init__(self):  # 实例化对象后,init会被调用
#         print('这是init方法')
#
#     def __new__(cls, *args, **kwargs):   # cls代表类对象
#         # 继承原来的代码 --- 重写: 1.父类名.方法名(参数)  2.super().方法名()
#         # B类的父类是谁? --- object
#         print('这是new方法中的cls:', cls)
#         print('这是new方法')
#         return object.__new__(cls)  # 返回了一个东西(对象引用)
#
# # # 实例化对象
# b = B()
# print('这是B:', B)


# class Person(object):
#     # self 就是实例对象本身
#     def __init__(self):   # 3.利用这个实例对象来调用init方法,new产生的实例就是init里面的self
#         print('这是init方法')  # 4.执行init里面的代码
#         # print('init中的self:', self)
#
#     def __new__(cls, *args, **kwargs):
#         print('这是new方法')   # 1.先执行new中的代码,打印
#         # print('object.__new__(cls)是:', object.__new__(cls))   # object.__new__(cls) = 实例对象
#         return object.__new__(cls)  # 2.new返回Person类的实例对象
#
#
# p1 = Person()  # p1是实例对象
# print('这是p1:', p1)

# 1. init方法什么时候被自动调用:实例化的时候被调用
# 2.init方法中的self是从哪里来的:self是new方法创建出来的,
#   然后发送给init方法
# 3.new方法是干嘛的:创建实例对象

# 4.执行步骤:
# 一个对象的实例化先执行new方法,
# 如果没有写,默认调用object里的new方法,返回一个实例对象,然后再调用init方法,对这个对象进行初始化。

# class C:
#     def __init__(self):
#         print('init')
#
#     def __new__(cls, *args, **kwargs):
#         print('new')
#
#     def funa(self):   # 实例方法
#         print('funa')
#
# c1 = C()
# c1.funa()  # 没有返回对象,执行不了

# # 5.举例
# class QQmusic(object):
#     def __init__(self):
#         print('播放器初始化')
#
#     def __new__(cls, *args, **kwargs):
#         print('这是new方法')
#         # 1.创建对象时,new会被自动调用
#         print('创建对象,分配空间')
#         # 2.为对象分配空间
#         ins = super().__new__(cls)  # cls代表类对象
#         print('这是new中的ins:', ins)
#         # 3.返回对象引用(实例对象)
#         return ins
#
#
# qq = QQmusic()
# print('这个是实例对象:', qq)

2.单例模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# 1.单例模式是一种设计模式
# 是一个特殊的类,这个类只能创建一个实例
# 2.为什么要有单例模式?
# 节省内存空间,因为产生不同的对象,会有不同的内存地址,
# 造成资源浪费
# 3.单例的运用:任务管理器、回收站、日志、线程池

# 4.怎么实现单例模式:
# 1.通过@classmethod
# 2.通过装饰器实现
# 3.通过__new__实现
# 4.通过导入模块时实现

# class A:
#     pass
#
# a1 = A()
# a2 = A()
# print(id(a1))
# print(id(a2))  # 实例化一次就会创建一个内存空间

# 5.单例设计流程:(通过new方法实现)
# 1.定义一个类属性,记录单例模式的引用,初始值是None
# 2.重写new方法  -- 创建对象的关键
# 3.如果类属性为空,调用new方法分配空间返回对象引用,
#   并在类属性中记录结果
# 4.返回类属性中记录的对象引用


# class Eaxm(object):
#     # 记录第一个实例对象的引用
#     ins = None   # 类属性,初始值为空
#     def __new__(cls, *args, **kwargs):
#         # print(Eaxm.ins)  # 打印出类属性的值
#         # 1.判断类属性是否为空:
#         if Eaxm.ins is None:
#             # 2.调用父类object中的new方法,为第一个实例对象分配空间
#             Eaxm.ins = super().__new__(cls)
#             # 3.返回类属性保存的对象引用
#         return Eaxm.ins
#
# e = Eaxm()  # 实例化的一个对象
# print(id(e))
# # print('第一次实例化后的类属性', e.ins)
# e2 = Eaxm()  # 实例化的第二个对象
# print(id(e2))
# print('第二次实例化后的类属性', e.ins)
# e3 = Eaxm()
# print(id(e3))

# 单例模式实现的效果:每一次实例化对象所创建的都是同一个,
# 内存地址是一样的


# 6.hasattr()函数
# hasattr()判断对象是否包含对应的属性,参数是一个对象和一个字符串
# 如果字符串是对象的属性值,返回为True, 不然返回False

# class We:
#     age = 18  # 类属性
#     def test(self):  # 实例方法
#         print('这是test')
#
# w1 = We()
# print(hasattr(w1, 'test'))
# print(hasattr(We(), 'age'))

# 7.单例模式举例二
# class A:
#
#     def __init__(self):  # self 实例对象本身
#         self.name = 'ne'  # 实例属性
#
#     def __new__(cls, *args, **kwargs):  # cls  类对象本身
#         if not hasattr(cls, 'ins'):  # hasattr(cls, 'ins')返回为False  (没有实例属性时才为真,就为它分配空间,
#                                                                          #   从而保证只能创建一个实例对象)
#             cls.ins = super().__new__(cls)
#         return cls.ins
#
#
# a1 = A()
# a2 = A()
# print(id(a1))
# print(id(a2))

# print(not hasattr(A('zs'), 'ins'))  # True

3.property属性

在这里插入图片描述
在这里插入图片描述


# # 类属性、实例属性
# # 变量名 = 变量值
# # property属性: 把一个方法变成一个属性
# # 两种方式:
# # 1.类属性:在类中定义值为property对象的类属性
# # 2.装饰器:在方法上应用装饰器


# # 第一种:类属性  property方法()
# class Test:
#     def __init__(self):
#         self.n = 0  # 实例属性
#
#     def getn(self):  # 获取实例属性的值
#         return self.n
#
#     def setn(self, val):   # 修改
#         print('这是修改')
#         self.n = val
#
#     def deln(self):        # 删除
#         print('这是删除')
#         # del self.n
#
#     # 通过property方法,定义一个属性
#     # 有四个参数:前三个参数都是方法名,分别代表查看、修改、删除;
#     # 最后的参数是字符串,此参数是这个属性的描述信息(可写可不写)
#     pro = property(getn, setn, deln, '这是一个描述信息')
#
#
# # te = Test()
# # print(Test.pro.__doc__)  # 查看pro属性的描述信息
# # 通过pro来进行,  格式:对象名.属性名
# # print(te.pro)  # 调用getn方法
# # te.pro = 100   # 调用setn方法
# # del te.pro     # 调用deln方法
# # print(te.pro)
#
#
# # 通过对象名来进行增删改查
# # print(te.n)        # 查看
# # te.n = 10          # 修改
# # # del te.n         # 删除
# # # te.name = 'aaa'  # 添加
# # print(te.n)
#
#
# # 第二种:装饰器  @property
# # 新式类有三种:@property、  @方法名.setter、 @方法名.deleter
# # 注意:
# # 1.定义时,在实例方法的基础上加@property装饰器;仅有一个self参数
# # 2.调用时,无需括号
# # 3.property属性修饰的方法名要一样


# # class A:
# #     def funa(self):
# #         print('这是funa')
# #
# #     @property     # 使用装饰器对funb来进行装饰,会自动添加一个funb的属性
# #     def funb(self):
# #         print('这是funb')
# #
# #     @funb.setter   # 修改
# #     def funb(self, val):
# #         print('这个值是:', val)
# #         print('这是@funb.setter')
# #
# #     @funb.deleter
# #     def funb(self):
# #         print('这是@funb.deleter')
# #
# #
# # a = A()
# # # a.funa()   # 调用实例方法
# # a.funb     # 调用property属性
# # a.funb = 123  # 自动执行@funb.setter 修饰的funb方法
# # del a.funb    # 自动执行@funb.deleter 修饰的funb方法
#
#
# # 举例:
# class MT:
#     def __init__(self):
#         # 奶茶原价
#         self.price = 10
#         # 折扣
#         self.dist = 0.8
#
#     @property    # 获取
#     def milk(self):
#         print('奶茶的原价是%s元' % self.price)
#         N_price = self.price * self.dist
#         print('活动期间,奶茶价格是%s元' % N_price)
#
#     @milk.setter    # 修改
#     def milk(self, va):
#         self.price = va
#         print('物价上涨,奶茶价格变为了%s元' % self.price)
#
#     @milk.deleter
#     def milk(self):  #  删除
#         print('销量不好,奶茶店倒闭了')
#         del self.price
#
#
#
# mt = MT()
# mt.milk
# mt.milk = 20
# del mt.milk
# mt.milk
#
#

class MT:
    def __init__(self):
        self.price = 10
        self.disc = 0.8

    @property
    def milk(self):
        print(f'奶茶原价是:{self.price}元')
        n_price = self.price * self.disc
        print('双十一活动期间的价格是:%d' % n_price)

    @milk.setter
    def milk(self, price):
        self.price = price
        print('物价上涨了,现在价格为:%d' % self.price)

    @milk.deleter
    def milk(self):
        print('商家经营不善,倒闭了,以后不用来买了')
        del self.price

mt1 = MT()
mt1.milk
mt1.milk = 12
mt1.milk
del mt1.milk
mt1.milk

4.魔术方法

在这里插入图片描述

# 魔术方法:左右两个都有双下划线的方法
# class A:
#     pass
#
# print(dir(A))  # 查看魔术方法

# 1.__doc__ 查看类的描述信息
# class B:
#
#     """这是一个类的描述信息"""
#     name = 'jiuge'

# print(B.__doc__)

# 2.__module__ 表示当前操作的对象在哪个模块
# __class__ 表示当前操作的对象的类是什么

# from test import B
# b = B()
# print(b.__module__)   # 导入的模块
# print(b.__class__)    # 当前操作的类


# 3.  __del__  析构方法
# 删除对象时,会默认调用__del__方法
# class Test:
#     def __init__(self):
#         print('我是init方法')
#
#     def __del__(self):  # 析构方法在对象销毁的时候将被调用
#         print('我是del方法')
#         print('被销毁了')
#
# te = Test()
# del te   # 删除对象
# print('这是最后一句')

# 4.__call__ :允许类的实例像函数一样被调用
# 调用格式:对象名()  或者 类名()()
# class C:
#     def __init__(self):
#         print('这是init')
#
#     def __call__(self, *args, **kwargs):
#         print('这是call')

# 第一种:
# c1 = C()
# c1()
# 第二种:
# C()()

# 5.__str__ : 打印对象时,默认输出该方法的返回值
# str方法通常返回一个字符串,作为这个对象的描述信息

# class A:
#     def __str__(self):
#         return 'hello'  # 返回值必须有,一定是字符串类型
#
#
# a1 = A()
# print(a1)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值