当前位置: 首页 > news >正文

python生成器有几种写法,python生成器函数例子

大家好,小编来为大家解答以下问题,python生成器有几种写法,python生成器函数例子,今天让我们一起来看看吧!

本文部分参考:Python迭代器,生成器–精华中的精华 https://www.cnblogs.com/deeper/p/7565571.html

一 迭代器和可迭代对象

迭代器是访问集合元素的一种方式。火车头采集器AI伪原创。迭代器只能往前不会后退。迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素,仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件。

特点:

a)访问者不需要关心迭代器内部的结构,仅需通过next()方法或不断去取下一个内容

b)不能随机访问集合中的某个值 ,只能从头到尾依次访问

c)访问到一半时不能往回退

d)便于循环比较大的数据集合,节省内存

e)也不能复制一个迭代器。如果要再次(或者同时)迭代同一个对象,只能去创建另一个迭代器对象。

enumerate()的返回值就是一个迭代器,我们以enumerate为例:

a = enumerate(['a','b'])for i in range(2):    #迭代两次enumerate对象for x, y in a:print(x,y)print(''.center(50,'-'))

结果:

0 a
1 b
-----------------------分割线------------------------
-----------------------分割线------------------------

可以看到再次迭代enumerate对象时,没有返回值。

我们可以用linux的文件处理命令vim和cat来理解一下:

a) 读取很大的文件时,vim需要很久,cat是毫秒级;因为vim是一次性把文件全部加载到内存中读取;而cat是加载一行显示一行

b) vim读写文件时可以前进,后退,可以跳转到任意一行;而cat只能向下翻页,不能倒退,不能直接跳转到文件的某一页(因为读取的时候这个“某一页“可能还没有加载到内存中)。

正式进入python迭代器之前,我们先要区分两个容易混淆的概念:可迭代对象(Iterable)和迭代器(Iterator)

1.1可迭代对象

定义:迭代器是一个对象,不是一个函数。只要它定义了可以返回一个迭代器的__iter__方法,或者定义了可以支持下标索引的__getitem__方法,那么它就是一个可迭代对象。

注意: 集合数据类型,如list、tuple、dict、set、str都是可迭代对象Iterable,却不是迭代器Iterator。

如何判断一个对象是可迭代对象呢?可以通过collections模块的Iterable类型判断:

from collections import Iterable
print(isinstance([], Iterable))
print(isinstance({}, Iterable))
print(isinstance('abc', Iterable))
print(isinstance({'name':'join','age':23},Iterable))
print(isinstance(set([2,3]),Iterable))

结果为:

True
True
True
True
True

再看:

from collections import Iterator
print(isinstance([], Iterator))
print(isinstance({}, Iterator))
print(isinstance('abc', Iterator))
print(isinstance({'name':'join','age':23},Iterator))
print(isinstance(set([2,3]),Iterator))

结果为:

False
False
False
False
False

1.2迭代器

定义:任何实现了__iter__()和__next__()(python2中实现next())方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值。

这里我们来看一下迭代器和可迭代对象的使用方法。

问题:不适用for,while以及下表索引,怎么遍历一个list?

l1=[2,3,5]
iter_l1 = l1.__iter__() 
# 或者iter(iter_l1)
# iter(iter_l1)是python的内置函数,
# l1.__iter__()调用的是l1对象的__iter__()方法。
# 下面的next()函数和__iter__()函数类似。
print(next(iter_l1)) # 或print(iter_l1.__next__()
print(next(iter_l1))
print(next(iter_l1))
print(next(iter_l1))

结果为:

2
3
5
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-126-eb58865cb644> in <module>4 print(next(iter_l1))5 print(next(iter_l1))
----> 6 print(next(iter_l1))

结论:思路就是,先得到当前对象(当前对象是可迭代对象)的迭代器,然后每次执行next(iter_l1)就可以得到当前对象的一个值。

修改一下:

l1=[2,3,5]
iter_l1 = l1.__iter__() 
for i in iter_l1:print(i,end=',')

结果为:

2,3,5,

再次执行for语句如下:

for i in iter_l1:print(i,end=',')

此次返回结果为空,可以看到迭代器只能遍历一次对象,不能重复遍历。由于for语句可以自动处理StopIteration异常,所以这里没有报出StopIteration,而是没有任何结果。

看一个例子。我们想得到Fibonacci数列,思路是定义一个可迭代对象类Fib;然后在定义一个迭代器类FibIterator,使用方式是:
① 实例化一个可迭代对象: fib = Fib()
② 得到fib的一个迭代器: fib_iter = iter(fib)
③ 然后每次调用next(fib_iter)可得到fibonacci数列中的一个数。

class FibIterator():'''定义迭代器类'''def __init__(self,num,a,b,current):self.num = numself.a = aself.b = bself.current = currentdef __iter__(self):return selfdef __next__(self):if(self.num-1>=0):self.num = self.num-1self.current = self.aself.a = self.bself.b = self.b+self.current   #以上两步赋值操作可省略中间变量直接写为self.a,self.b = self.b,self.a+self,b return self.currentelse: raise StopIterationclass Fib:'''定义可迭代对象所属类'''def __init__(self,num): #num表示该数列的长度self.a = 1self.b = 2self.current=self.aself.num = numdef __iter__(self):return FibIterator(self.num,self.a,self.b,self.current)fib = Fib(20)
fib_iter = iter(fib)
for i in range(20):print(next(fib_iter),end=',')

结果为:

1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,

这里定义的Fibonacci类的__init__函数有一个参数num,表示一共得到几个fibonacci数。

由于可迭代对象是实现了__iter__()方法的,迭代器对象是实现了__iter__()和__next__()方法的,能否只定义一个迭代器类呢?

试一下。

class Fib:def __init__(self,num):self.num = numself.a = 1self.b = 2self.current = self.adef __iter__(self):return selfdef __next__(self):if(self.num-1>=0):self.num = self.num-1self.current = self.aself.a = self.bself.b = self.b+self.current   #以上两步赋值操作可省略中间变量直接写为self.a,self.b = self.b,self.a+self,b return self.currentelse: raise StopIterationfib = Fib(10)
for i in fib:print(i,end=',')

结果为:

1,2,3,5,8,13,21,34,55,89,

当我们再次执行for语句时,

for i in fib:print(i,end=',')

同上面的分析一样,结果为空。如果想再次得到fibonacci数列的前10个数,就必须重新实例化Fib对象。

结论:为什么不只保留Iterator的接口而还需要设计Iterable呢?

因为迭代器迭代一次以后就空了,那么如果list,dict也是一个迭代器,迭代一次就不能再继续被迭代了,这显然是反人类的;所以通过__iter__每次返回一个独立的迭代器,就可以保证不同的迭代过程不会互相影响。

另外,迭代器是惰性的,只有在需要返回下一个数据时它才会计算。所以,Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

下面的例子得到全体自然数(下面我们用生成器可以得到更简单的写法)。

class Natural:def __init__(self):passdef __iter__(self):return NaturalIterator()
class NaturalIterator:def __init__(self):self.beg=0self.current=self.begdef __iter__(self):return selfdef __next__(self):self.current += 1return self.current   # 显示前20个自然数
n1=Natural()
n1_iter = iter(n1)
for i in range(20):print(next(n1_iter),end=',')

结果为:

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,

作业:使用迭代器和可迭代对象实现得到全体fibonacci数。

二 生成器

2.1 生成器的定义和使用

定义:生成器其实是一种特殊的迭代器,它不需要再像上面的类一样写__iter__()和__next__()方法了,只需要一个yiled关键字。

生成器一定是迭代器(反之不成立)。

Python有两种不同的方式提供生成器:

  1. 生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。 yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
  2. 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象, 而不是一次构建一个结果列表

我们先用一个例子说明一下:

def generate_even():i=0while True:if i%2==0:yield ii += 1g=generate_even()
dir(g) # 可以看到里面有__iter__()方法和__next__()方法,所以生成器也是迭代器。for i in range(10):print(g.__next__(),end=',')

结果为:

0,2,4,6,8,10,12,14,16,18,

现在解释一下上面的代码:

我们知道,一个函数只能返回一次,即return以后,这次函数调用就结束了;

但是生成器函数可以暂停执行,并且通过yield返回一个中间值,当生成器对象的__next__()方法再次被调用的时候,生成器函数可以从上一次暂停的地方继续执行,直到下一次遇到yield语句(此时会返回yield后面的值,如果有的话)或者触发一个StopIteration。

了解协同程序:
a) 生成器的另外一个方面是协同程序的概念。协同程序是可以运行的独立函数调用,可以暂停或者挂起,并从程序离开的地方继续或者重新开始。

b) 可以在调用者和被调用的之间协同程序通信。

c) 在程序暂停时可以传参:举例来说,当协同程序暂停时,我们仍可以从其中获得一个中间的返回值,当调用回到程序中时,能够传入额外或者改变了的参数,但是仍然能够从我们上次离开的地方继续,并且所有状态完整。

生成器表达式类似于列表推导式,只是把[]换成(),这样就创建了一个生成器。

gen = (x for x in range(10))

下面我们用生成器来实现前面的fibonacci数列和全体自然数。

# 生成前n个fibonacci数
def fib(n):a, b = 0, 1count=0while True:if(count>n):breakcount += 1yield ba, b = b, a+bf = fib(20)
for item in f:print(item,end=',')

结果为:

1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,
def Natural():n=0while True:yield nn += 1
g_n1=Natural()
for i in range(20):print(next(g_n1),end=',')

结果为:

0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,

2.2 send方法

生成器函数最大的特点是可以接受外部传入的一个变量,并根据变量内容计算结果后返回。这是生成器函数最难理解的地方,也是最重要的地方,协程的实现就全靠它了。

看一个小猫吃鱼的例子:

def cat():print('我是一只hello kitty')while True:food = yieldif food == '鱼肉':yield '好开心'else:yield '不开心,人家要吃鱼肉啦'

中间有个赋值语句food = yield,可以通过send方法来传参数给food,试一下:

情况1)

miao = cat()    #只是用于返回一个生成器对象,cat函数不会执行
print(''.center(50,'-'))
print(miao.send('鱼肉'))

结果:

Traceback (most recent call last):
--------------------------------------------------File "C:/Users//Desktop/Python/cnblogs/subModule.py", line 67, in <module>print(miao.send('鱼肉'))
TypeError: can't send non-None value to a just-started generator

看到了两个信息:

a)miao = cat() ,只是用于返回一个生成器对象,cat函数不会执行

b)can’t send non-None value to a just-started generator;不能给一个刚创建的生成器对象直接send值

改一下,情况2)

miao = cat()
miao.__next__()
print(miao.send('鱼肉'))

那么到底send()做了什么呢?send()的帮助文档写的很清楚,’’‘Resumes the generator and “sends” a value that becomes the result of the current yield-expression.’’’;可以看到send依次做了两件事:

a)回到生成器挂起的位置,继续执行

b)并将send(arg)中的参数赋值给对应的变量,如果没有变量接收值,那么就只是回到生成器挂起的位置

但是,我认为send还做了第三件事:

c)兼顾__next__()作用,挂起程序并返回值,所以我们在print(miao.send(‘鱼肉’))时,才会看到’好开心’;其实__next__()等价于send(None)

所以当我们尝试这样做的时候:

def cat():print('我是一只hello kitty')while True:food = yieldif food == '鱼肉':yield '好开心'else:yield '不开心,人家要吃鱼肉啦'miao = cat()
print(miao.__next__())
print(miao.send('鱼肉'))
print(miao.send('骨头'))
print(miao.send('鸡肉'))

就会得到这个结果:

我是一只hello kitty
None
好开心
None
不开心,人家要吃鱼肉啦

我们按步骤分析一下:

a)执行到print(miao.next()),执行cat()函数,print了”我是一只hello kitty”,然后在food = yield挂起,并返回了None,打印None

b)接着执行print(miao.send(‘鱼肉’)),回到food = yield,并将’鱼肉’赋值给food,生成器函数恢复执行;直到运行到yield ‘好开心’,程序挂起,返回’好开心’,并print’好开心’

c)接着执行print(miao.send(‘骨头’)),回到yield ‘好开心’,这时没有变量接收参数’骨头’,生成器函数恢复执行;直到food = yield,程序挂起,返回None,并print None

d)接着执行print(miao.send(‘鸡肉’)),回到food = yield,并将’鸡肉’赋值给food,生成器函数恢复执行;直到运行到yield’不开心,人家要吃鱼肉啦’,程序挂起,返回’不开心,人家要吃鱼肉啦’,并print ‘不开心,人家要吃鱼肉啦’

大功告成,那我们优化一下代码:

def cat():msg = '我是一只hello kitty'while True:food = yield msgif food == '鱼肉':msg = '好开心'else:msg = '不开心,人家要吃鱼啦'miao = cat()
print(miao.__next__())
print(miao.send('鱼肉'))
print(miao.send('鸡肉'))

我们再看一个更实用的例子,一个计数器。

def counter(start_at = 0):count = start_atwhile True:val = yield countif val is not None:count = valelse:count += 1count = counter(5)
print(count.__next__())
print(count.send(0))

结果为5,0而不是5,6的原因:

①执行print(count.next()),程序运行到val = yield count(第一个yield语句)后挂起,然后返回yield后面的值,所以结果为5。

②执行print(count.send(0)),程序恢复到挂起点val = yield count,将send的参数0赋值给接受变量val,然后继续执行下面的语句,由于val=0,所以if val is not None条件为真,count = val,接着又来到yield语句(val = yield count),此时程序挂起,返回yield后面的值count=0。

综上:当执行next()方法时,程序会恢复到挂起点,依次执行yield语句下面的语句,最后再返回yield后面的值;而不是先返回yield后面的值,再执行yield后面的语句。

最后给出一张图说明Iterable,Iterator,Generator的关系:
gen2

补充几个小例子:

a)使用生成器创建一个range

def range(n):count = 0while count < n:yield countcount += 1

相关文章:

python生成器有几种写法,python生成器函数例子

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python生成器有几种写法&#xff0c;python生成器函数例子&#xff0c;今天让我们一起来看看吧&#xff01; 本文部分参考&#xff1a;Python迭代器&#xff0c;生成器–精华中的精华 https://www.cnblogs.com/deeper/p…...

动态动画弹窗样式css

点击下载图片素材 html <div class"popWin"> </div> <div class"popPic"><div class"popWinBtn01">查看证书</div><div class"wintips01">恭喜您已完成训练营学习任务&#xff0c;荣誉证书已发放…...

数据生成 | MATLAB实现WGAN生成对抗网络数据生成

数据生成 | MATLAB实现WGAN生成对抗网络数据生成 目录 数据生成 | MATLAB实现WGAN生成对抗网络数据生成生成效果基本描述程序设计参考资料 生成效果 基本描述 1.WGAN生成对抗网络&#xff0c;数据生成&#xff0c;样本生成程序&#xff0c;MATLAB程序&#xff1b; 2.适用于MATL…...

PHP实现每日蛋白质摄入量计算器

1.laravel 路由 //每日蛋白质摄入计算器Route::get(api/protein/intake, FormulaControllerproteinIntakeCal); 2.代码 /*** 每日蛋白质摄入计算器*/public function proteinIntakeCal(){$number intval($this->request(number));$goalFactor array(0.8, 1.16, 0.8, 1.16,…...

vue elment 表格内表单校验代码

<p v-if"scope.row.id">{{ scope.row.bidderCode }}</p><el-form-itemclass"formitem"v-else:prop"bidderCode scope.row.id":rules"getValidationRules(投标人/供应商代码, scope.row.id)"><el-input v-model&…...

如何在Stream流中分组统计

上面是今天碰到需求,之前就做过类似的分组统计,这个相对来说比较简单,统计的也少,序号和总预约人数这两部分交给前端了,不需要由后端统计,后端统计一下预约日期和检查项目和预约人数就行; Overridepublic List<ItemStatisticsVo> statistics(ItemStatisticsModel itemSta…...

windows程序基础

一、windows程序基础 1. Windows程序的特点 1&#xff09;用户界面统一、友好 2&#xff09;支持多任务:允许用户同时运行多个应用程序(窗口) 3&#xff09;独立于设备的图形操作 使用图形设备接口( GDI, Graphics Device Interface )屏蔽了不同硬件设备的差异&#…...

【LeetCode】买卖股票的最佳时机最多两次购买机会

买卖股票的最佳时机 题目描述算法分析程序代码 链接: 买卖股票的最佳时机 题目描述 算法分析 程序代码 class Solution { public:int maxProfit(vector<int>& prices) {int n prices.size();vector<vector<int>> f(n,vector<int>(3,-0x3f3f3f))…...

【C++ 记忆站】命名空间

文章目录 命名空间概念命名空间的定义1、正常的命名空间定义2、命名空间可以嵌套3、同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中 命名空间的使用1、加命名空间名称及作用域限定符2、使用using将命名空间中某个成员引入3、使用using namespac…...

《离散数学及其应用(原书第8版)》ISBN978-7-111-63687-8 第11章 11.1.3 树的性质 节 第664页的例9说明

《离散数学及其应用&#xff08;原书第8版&#xff09;》ISBN978-7-111-63687-8 第11章 11.1.3 树的性质 节 第664页的定理3的引申 定理3 带有i个内点的m叉树含有nmi1个顶点 见本人博文 内点定义不同的讨论 如果对于一个m叉正则树&#xff0c;即任意分支节点的儿子恰好有m个&am…...

【云原生】K8S存储卷:PV、PVC详解

目录 一、emptyDir存储卷二、hostPath存储卷三、nfs共享存储卷四、PVC 和 PV4.1 NFS使用PV和PVC4.2创建动态PV 一、emptyDir存储卷 容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出现一些问题。首先&#xff0c;当容器崩溃时&#xff0c;ku…...

谈谈IP地址和子网掩码的概念及应用

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、IP地址的概念 二、IP地址的分类 1、A类 …...

vue2 如何监听数组的变化

在Vue 2中&#xff0c;底层是通过重写数组的原型方法来实现对数组变化的监听。具体来说&#xff0c;Vue 2使用了一个名为Observer的类来劫持数组的原型方法&#xff0c;使其在调用这些方法时能够触发相应的变化通知。 当Vue 2初始化一个响应式对象时&#xff0c;如果对象是一个…...

CSS中的transform属性有哪些值?并分别描述它们的作用。

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ translate()⭐ rotate()⭐ scale()⭐ skew()⭐ matrix()⭐ scaleX() 和 scaleY()⭐ rotateX()、rotateY() 和 rotateZ()⭐ translateX() 和 translateY()⭐ skewX() 和 skewY()⭐ perspective()⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&…...

vue3跳转页面后 海康监控实例不销毁

第一个页面是这样的 跳转到新的页面 只有海康的监控没有消失 使用控制台审查元素也审查不到 解决方法&#xff1a;在vue3的销毁周期把海康的监控销毁掉 import { reactive, onDeactivated} from "vue"; const state reactive({oWebControl: null as any, //监控绑…...

Unity 射线检测

文章目录 1. 定义2. 重要类和方法2.1 Ray2.2 从屏幕发出射线&#xff1a;2.3 Raycast2.4 RaycastAll2.5 RaycastHit 碰撞信息2.6 layerMask 让射线检测只检测指定层级的对象 1. 定义 在Unity中&#xff0c;射线检测&#xff08;Raycasting&#xff09;是一种常用的技术&#x…...

微信支付报非法的密钥大小: Caused by: java.security.InvalidKeyException: Illegal key size

在Linux环境中出现 java.security.InvalidKeyException: Illegal key size 异常通常是由于Java默认的加密限制引起的。Java默认的加密强度限制了加密算法密钥的最大长度 方式一 1. 找到该目录 /usr/java/jdk1.8.0_121/jre/lib/security 2. 替换local_policy.jar 和 US_export_…...

React 调试开发插件 React devtools 的使用

可以在谷歌扩展应用商店里获取这个插件。如果不能访问谷歌应用商店&#xff0c;可以点此下载最新版 安装插件后&#xff0c;控制台出现 “Components” 跟 “Profiler” 菜单选项。 查看版本&#xff0c;步骤&#xff1a; 下面介绍 react devtools 的使用方式。 在 Component…...

linux 搜索命令

搜索命令 locate命令 搜索速度快&#xff0c;是按照数据库进行搜索的(数据库位置在/var/lib/mlocate/mlocate.db) locate abc.txt 这个数据库是在半夜通过cron执行updatedb建立的&#xff0c;有时候新创建的文件使用locate来搜索文件搜索不到&#xff0c;可能是因为文件的索引还…...

如何使用Spark/Flink等分布式计算引擎做网络入侵检测

如何使用Spark/Flink等分布式计算引擎做网络入侵检测 引言16 Distributed Abnormal Behavior Detection Approach Based on Deep Belief Network and Ensemble SVM Using Spark17 Spark configurations to optimize decision tree classification on UNSW-NB1518 A dynamic spa…...

基于php驾校驾驶理论考试模拟系统

驾校驾驶理论考试模拟系统&#xff0c;是基于php编程语言&#xff0c;mysql数据库进行开发&#xff0c;本系统分为用户和管理员两个角色&#xff0c;其中用户可以注册登陆系统&#xff0c;查看考试规则&#xff0c;进行驾照考试&#xff0c;查看考试得分&#xff0c;考试错题&a…...

vue3+elementPlus table里添加输入框并提交校验

<template><div><el-form :model"info" ref"forms"><el-tableref"tableRef":data"info.data"border><el-table-column align"center" property"name" label"*姓名"><…...

ios swift5 collectionView 瀑布流(两列)

文章目录 1.瀑布流1.1 demo地址1.2 记得把部署的最低版本由8改成11,13甚至更高。不然编译会报错 2.动态计算图片和文字的高度 1.瀑布流 1.1 demo地址 CollectionViewWaterfallLayout - github 1.2 记得把部署的最低版本由8改成11,13甚至更高。不然编译会报错 2.动态计算图片和…...

创建一个简单的HTML Viewer应用程序

使用wxPython和内嵌浏览器来创建一个简单的HTML Viewer应用程序。 在本篇文章中&#xff0c;我们将使用Python和wxPython模块来创建一个简单的HTML Viewer应用程序。这个应用程序可以让用户输入HTML内容&#xff0c;并在内嵌浏览器中显示该内容的效果。 准备工作 在开始之前…...

无公网IP,公网SSH远程访问家中的树莓派教程

文章目录 前言 如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar内网穿透4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地…...

「UG/NX」Block UI 超级截面SuperSection

✨博客主页何曾参静谧的博客📌文章专栏「UG/NX」BlockUI集合📚全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C+&#...

高层建筑全景vr火灾隐患排查模拟培训软件助力群众防范火灾伤害

随着城市化进程的加快&#xff0c;楼宇建筑的数量也在不断增加。然而&#xff0c;楼宇消防安全问题也日益突出。为了提高楼宇员工和居民的消防安全意识&#xff0c;楼宇VR消防安全教育培训应运而生。VR安全培训公司深圳华锐视点制作的楼宇vr消防安全教育培训&#xff0c;包括消…...

【WPF】 本地化的最佳做法

【WPF】 本地化的最佳做法 资源文件英文资源文件 en-US.xaml中文资源文件 zh-CN.xaml 资源使用App.xaml主界面布局cs代码 App.config辅助类语言切换操作类资源 binding 解析类 实现效果 应用程序本地化有很多种方式&#xff0c;选择合适的才是最好的。这里只讨论一种方式&#…...

VS2017编译同事VS2022创建的库,报错无法运行rc.exe

项目场景&#xff1a; 项目场景&#xff1a;有一个qt的版本&#xff0c;迁移到VS中进行开发编译&#xff0c;同事使用的是VS2022已经编译成功。但是拷贝到我电脑&#xff0c;我使用VS2017打开编译&#xff0c;却报错&#xff1a;报错无法运行rc.exe。 原因分析&#xff1a; 1.…...

Leetcode49. 字母异位词分组

给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 解题思路&#xff1a;计数 思路&#xff1a;题意是字符串的字符都是小写&#xff0c;可以对每个字符串统计其中字符的…...