Python常见面试题017: Python中是否可以获取类的所有实例
017. Python中是否可以获取类的所有实例
出处
https://docs.python.org/zh-cn/3.9/faq/programming.html#faq-multidimensional-list
官方回答:Python 不会记录类(或内置类型)的实例。可以在类的构造函数中编写代码,通过保留每个实例的弱引用列表来跟踪所有实例
所以答案是不可以?可以?
准确的说是python不提供这样的接口(没做好)给你,但你要自己实现是么有问题的。
实现代码
方式一
class A:
instances = []
def __init__(self,name):
self.name = name
self.__class__.instances.append(self)
class B:
instances = {}
def __init__(self,name):
self.__class__.instances[self] = name a1 = A('a1')
a2 = A('a2')
print(A.instances) # [<__main__.A object at 0x00000250F285FAC0>, <__main__.A object at 0x00000250F285F7F0>]
print(A.instances[0].name) # a1 b1 = B('b1')
b2 = B('b2')
print(B.instances) # {<__main__.B object at 0x00000250F285F0A0>: 'b1', <__main__.B object at 0x00000250F285FEE0>: 'b2'}
方式一有点问题
比如你来个
c = A('c1'),你处理的是实例化传递的c1,如果 你要获取c这个变量名是做不到的方式二
from inspect import stack
class A:
instances = [] def __init__(self):
name = stack()[1].code_context[0].split('=')[0].strip()
self.instances.append(name) a = A()
b = A()
print(A.instances) # ['a','b']
你会发现关键是stack(),而这是inspect中的
详细你可以参考:https://docs.python.org/zh-cn/3.9/library/inspect.html?highlight=inspect
inspect.stack()
inspect.stack(context=1)
返回调用者的栈的帧记录列表。第一个记录代表调用者,最后一个记录代表了栈上最外层的调用。 在 3.5 版更改: 返回一个 具名元组 FrameInfo(frame, filename, lineno, function, code_context, index) 的列表。 具名元组:named tuple 可以参考 https://docs.python.org/zh-cn/3.9/glossary.html#term-named-tuple
方式二一样有问题
比如你对实例进行了del操作(这可能是显式的,也可能是隐式的),那你的处理是有问题的
from inspect import stack
class A:
instances = [] def __init__(self):
name = stack()[1].code_context[0].split('=')[0].strip()
self.instances.append(name) a = A()
del a
print(A.instances) # ['a'] # 没错你仍然能得到这个a
回到最开始的官方回答:
通过保留每个实例的弱引用列表来跟踪所有实例,弱引用是啥?你可能要去看下官网
https://docs.python.org/zh-cn/3.9/library/weakref.html
简而言之是:对对象的弱引用不能保证对象存活:当对象的引用只剩弱引用时, garbage collection 可以销毁引用并将其内存重用于其他内容。但是,在实际销毁对象之前,即使没有强引用,弱引用也一直能返回该对象。术语 referent 表示由弱引用引用的对象。
实现弱引用的模块是weakref
weakref返回一个类似其他语言指针的东西,在不影响python内建gc垃圾收集的情况下,创建一个指向该instance的弱引用。你可以理解python的gc机制类似于检测当前有没有任何引用该实例的对象,其中weakref就是创建一个新的引用,但这个引用在gc机制看来是“不存在”的,当只剩下weakref的时候gc就可以回收这块内存了
方式三
from inspect import stack
from weakref import proxy class A:
instances = [] def __init__(self):
self.name = stack()[1].code_context[0].split('=')[0].strip()
self.instances.append((self.name,proxy(self)))
def __del__(self):
try:
for name_instance in self.instances:
if name_instance[1] == self:
A.instances.remove(name_instance)
except ReferenceError:
print('引用被删了')
# for name_instance in self.instances:
# if name_instance[1] == self:
# A.instances.remove(name_instance)
# ReferenceError: weakly-referenced object no longer exists
a1 = A()
del a1 # 显式的删除 ,但del是不一定会触发__del__的,因为可能还有别的引用
def func():
a2 = A() # a2 也是一个实例,但它出了这个函数也不会存在
func()
a3 = A()
print(A.instances) # 只有a3
# [('a3', <weakproxy at 0x0000013C5A7A43B0 to A at 0x0000013C5A5FF760>)]
拓展
在stackoverflow上很早就有人问过类似的问题
https://stackoverflow.com/questions/328851/printing-all-instances-of-a-class
https://stackoverflow.com/questions/54000173/how-to-get-all-instances-of-a-class
有一些有趣的代码你可以看下(稍作更改)
def get_obj_instance_nums(dest_obj):
'''
获取对象的个数
'''
import gc
obj_instance = []
for obj in gc.get_objects():
if isinstance(obj, dest_obj):
obj_instance.append(obj)
return len(obj_instance) class A:
pass
a1 = A()
a2 = A()
del a1 # 你如果删了,那返回1,不删就返回2
print(get_obj_instance_nums(A)) # 1
弱引用的另外一个示例
from collections import defaultdict
import weakref class KeepRefs(object):
__refs__ = defaultdict(list)
def __init__(self):
self.__refs__[self.__class__].append(weakref.ref(self)) @classmethod
def get_instances(cls):
for inst_ref in cls.__refs__[cls]:
inst = inst_ref()
if inst is not None:
yield inst class X(KeepRefs):
def __init__(self, name):
super(X, self).__init__()
self.name = name x = X("x")
y = X("y")
for r in X.get_instances():
print r.name
del y
for r in X.get_instances():
print r.name
Python常见面试题017: Python中是否可以获取类的所有实例的更多相关文章
- 整理的最全 python常见面试题(基本必考)
整理的最全 python常见面试题(基本必考) python 2018-05-17 作者 大蛇王 1.大数据的文件读取 ① 利用生成器generator ②迭代器进行迭代遍历:for line in ...
- 整理的最全 python常见面试题
整理的最全 python常见面试题(基本必考)① ②③④⑤⑥⑦⑧⑨⑩ 1.大数据的文件读取: ① 利用生成器generator: ②迭代器进行迭代遍历:for line in file; 2.迭代 ...
- 【转载】常见面试题:C#中String和string的区别分析
在很多人面试C#开发工程师的时候,会遇到一个面试题,就是C#中String和string有啥区别.其实针对这个问题C#中String和string没有本质上的区别,两者在程序中都可使用,稍微的一个区别 ...
- 【python常见面试题】之python 中对list去重的多种方法
在python相关职位的面试过程中,会对列表list的去重进行考察.(注意有时会要求保证去重的顺序性) 1.直观方法 li=[1,2,3,4,5,1,2,3] new_li=[] for i in l ...
- Python常见面试题
Q 1:Python 有哪些特点和优点? 作为一门编程入门语言,Python 主要有以下特点和优点: ● 可解释● 具有动态特性● 面向对象● 简明简单● 开源● 具有强大的社区支持当然,实际上 Py ...
- python常见面试题(三)
问题1 到底什么是Python?你可以在回答中与其他技术进行对比(也鼓励这样做). 答案 下面是一些关键点: Python是一种解释型语言.这就是说,与C语言和C的衍生语言不同,Python代码在运行 ...
- 常见面试题整理--Python概念篇
希望此文可以长期更新并作为一篇Python的面试宝典.每一道题目都附有详细解答,以及更加详细的回答链接.此篇是概念篇,下一篇会更新面试题代码篇. (一).这两个参数是什么意思:*args,**kwar ...
- python常见面试题(二)
1. 到底什么是Python?你可以在回答中与其他技术进行对比(也鼓励这样做). 下面是一些关键点: Python是一种解释型语言.这就是说,与C语言和C的衍生语言不同,Python代码在运行之前不需 ...
- python常见面试题(mark)
1.大数据的文件读取 ① 利用生成器generator ②迭代器进行迭代遍历:for line in file 2.迭代器和生成器的区别 1)迭代器是一个更抽象的概念,任何对象,如果它的类有next方 ...
- python常见面试题(一)
1.Python是如何进行内存管理的? 答:从三个方面来说,一对象的引用计数机制,二垃圾回收机制,三内存池机制 一.对象的引用计数机制 Python内部使用引用计数,来保持追踪内存中的对象,所有对象都 ...
随机推荐
- cat、more、less、tail、head文件查看指令辨析
1.cat 简介 cat [OPTION]... [FILE]... cat 可以将多个文本连接起来并输出,当省略输入文件或输入文件用字符-替代时,读取标准输入 常用参数 -n \(~~~~\)输出行 ...
- jsp第九周作业
1.做一个图书类Book id,name,price ,get,set访问器,构造方法2个,1个无参,1个有参做一个测试类,在main中创建3个图书对象,放到list集合中.做一个菜单,可以添加,删除 ...
- 关于数据传递 json
关于这几种语言的json 操作 Lua local cjson2 = require "cjson" local lua_object = { ["name"] ...
- 基于Nginx以及web服务器搭建在线视频播放
安装Nginx Nginx官网下载地址 网址打开后如图 下载windows版本的Nginx,这里下载最新的1.18.0版本 Nginx在windows下的安装只需要将其解压缩即可.建议将解压后的目录移 ...
- Python - XSS-href
参考资料: https://owasp-skf.gitbook.io/asvs-write-ups/cross-site-scripting-href-xss-href/kbid-3-cross-si ...
- binom_test
bt <- function(a, b, p = 0.5) {binom.test(a, b+a, 0.5, alternative= c("two.sided"), con ...
- 01 docker容器技术基础入门
本章内容: 1.container是什么? 2.LXC技术介绍 3.namespaces-名称空间,实现资源隔离 4.容器的资源分配--Cgroup,实现资源分配 5.LXC与dockers ---- ...
- Must be called at the top of a `setup` function vue3使用vue-i18n时出现的报错
在某js文件中引入 import {useI18n} from "vue-i18n"; 使用:useI18n().t('APP_LOADING') 修改后: import i18n ...
- 【Airtest相关】收集一些Airtest的介绍
1.项目简介 ui自动化一直是个让人头疼的事,主要是因为系统兼容性难度较大和开发维护成本比较高, 以前使用过appium,通用性比较差,并且开发有一定的基础才行,更难以忍受的是后期的维护成本:然后接触 ...
- RecyclerView显示列表
本次要讲的内容是利用RecyclerView显示Users列表的信息,如下图所示. 首先我们来创建模型User.java package com.example.mytest.User; import ...