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)