0
点赞
收藏
分享

微信扫一扫

python学习高级篇(part9)--对象的引用计数

学习笔记,仅供参考,有错必纠


文章目录

  • ​​python 学习高级篇​​
  • ​​类对象的特殊方法之`__str__()`​​
  • ​​类对象的特殊方法之`__new__()`​​
  • ​​对象的引用计数​​
  • ​​什么是引用计数​​
  • ​​对象的引用计数加1的情形​​
  • ​​对象的引用计数减1的情形​​


python 学习高级篇



# 支持多行输出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all' #默认为'last'



类对象的特殊方法之​​__str__()​



在python的交互式界面中,我们敲入如下代码

"""
>>> class MyClass(object):
... pass
...
>>> mc = MyClass()
>>> mc
<__main__.MyClass object at 0x103f41550>
>>> print(mc)
<__main__.MyClass object at 0x103f41550>
>>> str(mc)
'<__main__.MyClass object at 0x103f41550>'
>>> repr(mc)
'<__main__.MyClass object at 0x103f41550>'
"""

"""
>>> class MyClass(object):
... def __str__(self):
... return "__str__被调用"
...
>>> mc = MyClass()
>>> mc
<__main__.MyClass object at 0x103e5c588>
>>> print(mc)
__str__被调用
>>> str(mc)
'__str__被调用'
>>> repr(mc)
'<__main__.MyClass object at 0x103e5c588>'
"""

"""
>>> class MyClass(object):
... def __repr__(self):
... return "__repr__被调用"
...
>>> mc = MyClass()
>>> mc
__repr__被调用
>>> print(mc)
__repr__被调用
>>> str(mc)
'__repr__被调用'
>>> repr(mc)
'__repr__被调用'
"""

"""
>>> class MyClass(object):
... def __str__(self):
... return "__str__被调用"
... def __repr__(self):
... return "__repr__被调用"
...
>>> mc = MyClass()
>>> mc
__repr__被调用
>>> print(mc)
__str__被调用
>>> str(mc)
'__str__被调用'
>>> repr(mc)
'__repr__被调用'
"""
'\n>>> class MyClass(object):\n...     def __str__(self):\n...         return "__str__被调用"\n...     def __repr__(self):\n...         return "__repr__被调用"\n... \n>>> mc = MyClass()\n>>> mc\n__repr__被调用\n>>> print(mc)\n__str__被调用\n>>> str(mc)\n\'__str__被调用\'\n>>> repr(mc)\n\'__repr__被调用\'\n'

类对象的特殊方法之​​__str__()​​​和​​__repr__()​​用于自定义并返回实例对象的字符串表示形式

  • 当在交互式命令行中直接打印一个实例对象时,如果在实例对象对应的类对象中实现了特殊方法​​__repr__()​​,会自动调用该方法;否则,会打印实例对象对应的类对象和实例对象在内存中的地址。
  • 当调用内置函数print打印一个实例对象时,如果在实例对象对应的类对象中实现了特殊方法​​__str__()​​​,会自动调用该方法;否则,如果在实例对象对应的类对象中实现了特殊方法​​__repr__()​​,会自动调用该方法;否则,会打印实例对象对应的类对象和实例对象在内存中的地址。
  • 当调用内置函数str创建字符串并且实参是一个实例对象时,如果在实例对象对应的类对象中实现了特殊方法​​__str__()​​​,会自动调用该方法;否则,如果在实例对象对应的类对象中实现了特殊方法​​__repr__()​​,会自动调用该方法;否则,会打印实例对象对应的类对象和实例对象在内存中的地址。
  • 当调用内置函数repr创建字符串并且实参是一个实例对象时,如果在实例对象对应的类对象中实现了特殊方法​​__repr__()​​,在内置函数repr的内部会自动调用该方法;否则,会打印实例对象对应的类对象和实例对象在内存中的地址。

通常情况下,类对象的特殊方法​​__str__()​​​和​​__repr__()​​的实现代码是一样的,因此当实现了其中一个后,可以把其方法名赋值给另一个的方法名。

class MyClass(object):
def __str__(self):
return 'XXX'
__repr__ = __str__

内置函数str()和repr()都返回对象的字符串表示,其区别在于:

  • str()的返回值是给用户看的,更加用户友好;
  • repr()的返回值是给程序开发者看的,是为调试服务的。
str('A \nB')
repr('A \nB')
'A \nB'




"'A \\nB'"



类对象的特殊方法之​​__new__()​



当使用"类名([实参])"创建实例对象时,Python解释器的主要处理过程包括两大步:

  • 调用特殊方法​​__new__()​​​创建实例对象:首先会查找该类对象是否实现了特殊方法​​__new__()​​​,如果没有实现,则去其父类中依次查找,直到类对象object;特殊方法​​__new__()​​会返回创建的实例对象.
  • 调用特殊方法​​__init__()​​​对创建的实例对象进行初始化,​​__new__()​​​返回的实例对象会作为实参被自动传递给​​__init__()​​​的第一个形参​​self​​.
class Parent(object):
def __new__(cls, *args, **kwargs):
print("父类的__new__()被调用,其形参cls对应实参的id:%s" % id(cls))
obj = super().__new__(cls)
print("创建的实例对象的id:%s" % id(obj))
return obj

class Child(Parent):
def __init__(self, name):
print("子类的__init__()被调用,其形参self对应实参的id:%s" % id(self))
self.name = name

print("父类的id:%s" % id(Parent))
print("子类的id:%s" % id(Child))

child = Child("Mike")
print("创建的实例对象的id:%s" % id(child))
父类的id:1968492033576
子类的id:1968492039240
父类的__new__()被调用,其形参cls对应实参的id:1968492039240
创建的实例对象的id:1968521654224
子类的__init__()被调用,其形参self对应实参的id:1968521654224
创建的实例对象的id:1968521654224

python学习高级篇(part9)--对象的引用计数_python



对象的引用计数



什么是引用计数



通常情况下,开发人员无需关心内存的分配和释放。当创建一个对象时,系统会自动分配一块内存以存储该对象的信息。当该对象不再被使用时,系统会进行垃圾回收以自动释放掉其占用的内存。

为了确保使用中的对象不会被销毁,Python使用引用计数来跟踪和计算内存中每个对象被引用的次数。当对象的引用计数为0时,它才可以被销毁。



对象的引用计数加1的情形



  1. 对象赋值给变量
  2. 引用对象的变量赋值给另一个变量
  3. 对象作为容器(例如:列表、元组、集合等)中的元素
  4. 对象作为函数调用时的实参
class MyClass(object):
pass

def do_sth(param):
pass

# 引用计数加1,变为1
a = MyClass()
# 引用计数加1,变为2
b = a
# 引用计数加1,变为3
L = [1, 2, a]
# 在函数的执行过程中,引用计数加1,变为4
do_sth(a)
# 当函数执行后,对实参的引用会自动销毁,因此,引用计数减1,变为3
import sys
# 在函数的执行过程中,引用计数加1,变为4
print(sys.getrefcount(a))
# 当函数执行后,对实参的引用会自动销毁,因此,引用计数减1,变为3
4

python学习高级篇(part9)--对象的引用计数_python_02



对象的引用计数减1的情形



  1. 对象离开它的作用域,例如:对象所在的函数执行完毕
  2. 对象的引用被显式销毁
  3. 引用对象的变量被赋予新的对象
  4. 从容器中删除对象,或对象所在的容器被销毁
class MyClass(object):
pass

# 引用计数加1,变为1
x = MyClass()
# 引用计数加1,变为2
y = x
# 引用计数减1,变为1
del x
# 引用计数加1,变为2
z = y
# 引用计数减1,变为1
y = 18
# 引用计数加1,变为2
l = [1, 2, z]
# 引用计数减1,变为1
del l
# 在函数的执行过程中,引用计数加1,变为2
print(sys.getrefcount(z))
# 当函数执行后,对实参的引用会自动销毁,因此,引用计数减1,变为1
2

python学习高级篇(part9)--对象的引用计数_python_03

举报

相关推荐

0 条评论