caimouse
在IT行业有20多年的经验。拥有20多年的C和C++开发经验,5年以上Python开发经验,资深数据库开发、上百G数据库优化经验。曾经任职嵌入式工程师、P2P开发工程师、银行信用卡交易系统工程师、全自动化电池测试部门经理。
展开
-
C++里使用二分法查找和lambda表达式进行比较
C++里使用二分法查找和lamda表达式进行比较在软件开发里,经常会遇到排序的数据搜索的问题,而这样的问题,往往就是使用二分法查找的速度最快了。但是自己去从头写一个二分法的算法,往往会容易出错,这时候就需要使用STL里的算法函数库,这样就比较快速地完成功能,而不会出错。不过学习STL里的算法函数,也是一个负担,不过还是值得的,因为从来就没有不劳而获的成果,必须自己去努力学习,不断地练习才能应用到实际场合中,才可以在压力情况下运用出来。a.binary_search:查找某个元素是否出现。原创 2021-12-31 16:42:21 · 355 阅读 · 0 评论 -
更新vs2019 后,在指定-T v141_xp情况下载编译会报下面warning MSB8051
需要修改下面的文件:VS2019\MSBuild\Microsoft\VC\v150\Platforms\Win32\PlatformToolsets\v141_xp文件内容如下:<!--***********************************************************************************************Toolset.targetsWARNING: DO NOT MODIFY this file unle原创 2021-12-30 17:44:48 · 1017 阅读 · 1 评论 -
Python里 int 和 bytes互转的方法
Python里 int 和 bytes互转的方法在Python3之前,一般是使用下面的方法:>>> import struct>>> struct.pack("B", 2)'\x02'>>> struct.pack(">H", 2)'\x00\x02'>>> struct.pack("<H", 2)'\x02\x00'也就是使用struct.pack方法,它实现了从int到bytes的转换。在Pyt原创 2021-10-07 09:05:05 · 5672 阅读 · 0 评论 -
C++ 库boost里使用定时器计时
在程序里常常需要使用计时的动作,并且计时有三种形式,一种是系统日历的时钟,也叫做系统时间(wall clock time, elapsed time), 是指一段程序从运行到终止,系统时钟走过的时间。一般来说,系统时间都是要大于CPU时间的。通常这类时间可以由系统提供,在C++/Windows中,可以由<time.h>提供。注意得到的时间精度是和系统有关系的。第二个是进程运行CPU的时间,执行调用进程的用户指令所花费的CPU时间。第三个是系统调用进程的时间。在boost定时器类里定义原创 2021-08-03 23:33:27 · 2022 阅读 · 0 评论 -
C++使用boost 1.75版本来读写JSON文件
目前使用JSON文件的机会越来越大了,因为它简单,并且可读,无论是网络的协议交换,还是保存的文件格式,都是越来越多。无论是C++,还是python,或者JS,都是需求越来越多。在C++里使用JSON的库也很多,但是使用boost库还是比较方便和快捷。Boost就已经有能够解析JSON的库了,名字叫做Boost.PropertyTree。Boost.PropertyTree不仅仅能够解析JSON,还能解析XML,INI和INFO格式的文件。但是由于成文较早及需要兼容其他的数据格式,相比较于其他的C++原创 2021-07-10 17:16:47 · 1266 阅读 · 0 评论 -
当你在python的fstring中看到 !r,!a,!s,是不是很奇怪?
首先是fstring的结构f ' <text> { <expression> <optional !s, !r, or !a> <optional : format specifier> } <text> ... ''!s'在表达式上调用str(),'!r'调用表达式上的repr(),'!a'调用表达式上的ascii()。语法上是这样定义的:If a conversion is specified, the result o原创 2021-07-03 09:21:58 · 305 阅读 · 0 评论 -
使用pybind11开发python扩展库(11)
前面学习的内容,都是面向python的扩展,现在来学习另一个方向,面向C++的扩展。比如高性能,或者框架,使用C++编程,然后灵活的代码使用python来编程,这样达到最佳组合。比如在游戏服务领域,可以采用C++来写高性的网络处理,高性能框架,但是游戏的逻辑和玩法,就可以使用python来开发,这样服务器不需要重新启动,也可以快速地更新,也可以大幅度地降低开发成本,也可以大大提高项目的开发速度。因此,需要来学习把python当作一门脚本的方式。使用pybind11来创建嵌入式的脚本是非常容易的,下面就来原创 2021-07-02 11:49:56 · 404 阅读 · 0 评论 -
使用pybind11开发python扩展库(10)
前面学习了从c++里导出类到python里使用,这是比较简单的方式,也是最基本的内容。接着下来我们来学习更高级的一些内容,比如C++里写一些虚函数,或者叫做接口函数,这些函数按理是可以在C++里的派生类进行重写,这是比较明白确认的事情了。但是你也许会问一下,如果这些接口函数需要在python里也能重写这些虚函数行吗?目前还是不能直接就可以重写的,需要采用第二个对象的方法才可以,这里需要一个临时对象的技巧才可以。下面我们就来通过例子来学习这种技巧,让你的小伙伴在python使用C++的对象更加舒服。假原创 2021-06-30 09:52:37 · 326 阅读 · 0 评论 -
使用pybind11开发python扩展库(9)
Keyword-Only参数在python 3引入Keyword-Only参数,目前在pybind11也提供了支持。对这个星号*的定义和描述在[PEP 3102]中。星号可以以一个参数的形式出现在函数声明中的参数列表中,但星号之后的所有参数都必须有关键字(keyword),这样在函数调用时,星号*之后的所有参数都必须以keyword=value的形式调用,而不能以位置顺序调用。def f(a, *, b): # a can be positional or via keyword; b m.原创 2021-06-26 11:37:32 · 258 阅读 · 0 评论 -
使用pybind11开发python扩展库(8)
相对前面的函数返回值时的策略相比,其实还有调用策略,也就是保证函数调用时参数的生存期和状态。保持策略(Keep alive)大多数情况下,这种策略都是应用于容器与容器中的元素的生命周期处理。因为当容器还在生存周期中,而其中保持的元素失效了,那么就会发生灾难性的问题,这时候去访问这样的元素,就会导致程序出错。因此pybind11提供了一个方法让函数调用时的参数,保持与容器的生命周期一样长。比如引用函数keep_alive,这个函数的作用就是让病人Patient保持生存周期至少要长过护士Nurse。原创 2021-06-25 12:13:25 · 434 阅读 · 0 评论 -
使用pybind11开发python扩展库(7)
函数当你要想学习下面的内容之前,一定要先学会前面的内容,比如导出简单的类和函数,这样才有相应的基础来学习下面的内容。下面介绍的内容适合普通的C++函数,也适合C++里类的函数,以及python里叫做方法的函数。函数返回值的策略由于Python和C++采用不同的方法来管理内存,以及对象的生命周期。这样导致了绑定函数刚刚靠返回的类型来解决内存管理和对象生命周期会出问题。为了解决这个问题,pybind11提供了一个返回类型策略来管理内存和对象的生命周期,可以传送给module_::def()和ca原创 2021-06-24 22:50:59 · 292 阅读 · 0 评论 -
使用pybind11开发python扩展库(6)
前面介绍了怎么样通过C++11快速地开发python的扩展库,也提供多种方式来导出C++的特性,也满足了python的一些特性的要求。这样是非常方便地编写python扩展库,提高了运行效率和开发效率。这些都做完成之后,就来到了下一个环节,也就是自动化安装的阶段,即使你有最好的代码,也有最好优化的运行效率,但是安装不容易,或者缺少安装这个环节,其它的工作还是等于0,为什么这样说呢?因为没有客户愿意使用你的代码,你的库,就不会给你钱。所以接着下来,我们来学习制作pybind11的安装包。如果我们从头来编写一原创 2021-06-24 20:45:00 · 276 阅读 · 0 评论 -
使用pybind11开发python扩展库(5)
前面学习了继承类的导出,可见完美地完成了这一个工作,如果想掌握一些深入的内容,还是需要继续向前,比如类的多态下是怎么样导出的呢?如果我们创建一个派生类,然后导出是一个基类的指针,那么我们可以访问派生类的内容吗?为了解决这个心中的疑惑,我们来继续走上学习的征途。先来创建两个有继承关系的类,并且有虚拟函数的声明,这样才会创建虚拟表,代码如下:struct PolymorphicPet { virtual ~PolymorphicPet() = default;};struct Polymorp原创 2021-06-24 11:23:19 · 266 阅读 · 0 评论 -
使用pybind11开发python扩展库(4)
当我们使用python的类时,可以动态地添加属性到类里去,这是基本的工作机制,但是在C++语言里的类是固定的,也就是说在编译之后是固定的,不会变化。因此要想让C++里导出的类支持python这种特性,必须有一些改变才可以。现在就来搞明白怎么样让C++里导出的类支持这个特性。这时需要引入使用py::dynamic_attr()特性,经过它处理之后,就可以让C++类导出之后具备动态添加成员变量的功能,声明如下: py::class_<MyPet>(m, "MyPet", py::dynam原创 2021-06-24 09:34:43 · 301 阅读 · 0 评论 -
使用pybind11开发python扩展库(3)
面向对象的类和结构怎么样导出?由于类和结构都属于自定义类型,要想导出这样的类型给python使用,必须使用另外一种方式,就是创建与python里一样的类结构。下面通过一个结构定义为Pet的例子来说明:struct Pet { Pet(const std::wstring &name) : name(name) { } void setName(const std::wstring &name_) { name = name_; } const std::wstring &am原创 2021-06-23 11:28:40 · 246 阅读 · 0 评论 -
使用pybind11开发python扩展库(1)
前面介绍了怎么快速地使用C++11来开发python的扩展库,这样可以更快地提高python的代码运行和计算性能,这样可以把关键代码做优化,非关键代码就使用python来开发就行了,这样混合开发方式比go更加快方便快捷,性能也比go好,比java更好十倍以上。可以这种方式是无敌的工具组合。现在来学习怎么样在C++的开发模块里让输入关键字参数,比如像下面这种形式:import exampleexample.add(i=1, j=2)这样i和j就跟位置没有关系了,可以j放在前面,也可以放在后面。.原创 2021-06-22 20:52:26 · 412 阅读 · 1 评论 -
使用pybind11来快速开发python程序扩展库
开发python的C++扩展库有很多方法,比如使用原始的C接口,也是cpython的基本开发方法,这种方式对于一般人员来说不太友好,因为需要对它的类型和引用都非常熟悉。也有使用boost库的python库来开发,但是这个库太宠大了,需要完全编译之后才能使用。因此大家在想有没有一个既简单又快捷的开发库,它就是pybind11库,这个库由于使用C++11的特性,必须要支持C++11的编译器才可以使用。在下面的例子里是使用VC++2017来进行,它是支持C++11的特性的,所以完全可以编译正常。首先我们需要下原创 2021-06-21 22:29:14 · 338 阅读 · 0 评论 -
python 3.7使用protobuf-3.17.3版本
从前面一文里已经学会安装protobuf在VC2017里编译,有时候服务器使用python来开发,那么就需要与VC开发的客户端进行通讯,这样就需要协议进行通讯,这时候解包和打原创 2021-06-20 23:16:59 · 1428 阅读 · 0 评论 -
VC2017使用protobuf-3.17.3版本
序列化是一个永恒的主题,比如网络上协议的打包和解包,比如保存状态到文件以及从文件恢复状态,还有进程之间进行交换数据等等。使用protobuf协议有一个优势,就是可以自动化生成和自动化解包,...原创 2021-06-20 22:07:42 · 667 阅读 · 0 评论 -
C++比较方便访问Mysql数据库的类库QTL
之前看一个别人写的程序,里面需要访问Mysql数据库,还是使用自己的封装,但是极其难用,因此需要改写这部分代码,本来想自己重新写一个,感觉还是从网上找一个替换比较方便一些。因此就找到了QL...原创 2021-06-15 15:56:38 · 587 阅读 · 1 评论 -
编译和使用boost 1.75版本
随着时间向前推进,来到今天,boost库已经发布到最新的1.76.0版本。为了安全起见,目前还是使用1.75.0版本。以下就是基于1.75.0的版本来进行编译和测试,开发工具使用windows 10平台的VC2017社区版本。首先我们回来到下面这个网站:然后找到对应的版本下载,这里下载的是boost_1_75_0.7z版本,如果想快速地下载,可以使用迅雷来下载,可以几秒钟就下载完成了。接着使用解压工具解压到目录D:\kangjin\TestBoost\boost_1_75_0,然后我们.原创 2021-06-09 11:53:32 · 1225 阅读 · 2 评论 -
保持成长的三把钥匙:自律、自得和自省
保持成长的三把钥匙:自律、自得和自省1第一把钥匙,是自律。网上看到这样一个问题:怎么避免成为一个碌碌无为的人?有个网友答:“只要不随波逐流,就已经成功了一半。不能看别人吃完饭就追剧,自己也懒得运动;不能看别人周末在家玩一天手机,自己也丢掉手里的书,白白耗掉一整天。”一天天放纵自己,到后来身材走样、大脑一片空白;每天过得浑浑噩噩,只会不断耗尽对生活的热情。曾听过这样一句话:“我并不期待人生可以过得很顺利,但我希望碰到人生难关的时候,自己可以是它的对手。”而想要成长为一个可以直面难关的人,首先原创 2021-04-09 10:12:07 · 454 阅读 · 2 评论 -
《Fluent Python》读书笔记-2.9
如果你有很多数组要进行保存数据,并且进行查看和运算,那么你就必须要熟悉memorview的使用,否则你会导致处理数据效率低下。使用memorviewmemorview类是一个共享内存数据的类,当你使用它来切片数组时,并不需要拷贝数据就可以查看。因此,它被大量地使用在NumPy库里。memoryview本质上是Python本身的一种NumPy数组结构。它允许您在数据结构之间共享内存(比如PIL图像、SQLlite数据库、NumPy数组等),无需预先复制。这对于大型数据集是非常重要的。m..原创 2020-11-07 11:23:42 · 422 阅读 · 3 评论 -
《Fluent Python》读书笔记-2.8
在序列容器里有一个经常的操作,那就是排序。list.sort 和 内置sorted函数list.sort方法是把列表在原地进行排序的操作,也就是说不产生新的列表返回,它执行结束之后返回None。此方法返回None表示它不创建新的列表对象返回,并且它在原地修改了列表,这一个编程习惯在Python里形成了传统。因而所有Python的API函数或方法都遵守这个偏好,明确告诉调用者,它在原地对对象作了更改,并没有新对象创建返回。如果你去查看一下,会发现random.shuffle方法也遵守这个规..原创 2020-11-06 18:19:26 · 296 阅读 · 0 评论 -
《Fluent Python》读书笔记-2.7
大家经常使用Python就会发现有一些公共操作,比如对序列容器进行并接和重复。在Python里,主要通过加号(+)和乘号(*)来实现。+和*对容器操作Python编译器的开发人员使用+和*来实现对序列容器进行串联操作。当我们使用+来串联时,一般要求两个参数都是同一个类型的序列容器对象,当拼接完成之后是重新创建了一个新的对象,并不会影响原来的对象。为了拼接多个相同的对象,可以采用*来操作:>>> l = [1, 2, 3]>>> l * 5..原创 2020-11-05 15:56:40 · 391 阅读 · 0 评论 -
《Fluent Python》读书笔记-2.6
切片(Slicing)在所有序列容器,包括列表、元组、字符串等等,它们都支持切片操作,这是Python语言的强大武器,本文将开始学习切片的高级使用技巧。为什么切片和Range操作都不包括最后一项?从Python语法里知道,当进行切片操作时,比如mylist[0,2]的操作,并不包括最后一项[2]。同样range迭代生成也是不包括最后一项,这是到底是什么原因呢?其实它跟C语言和其它很多语言一样,下标变量的开始都是从0开始计算的。使用这样的约定有以下好处:1)容易看出来切片操作或ran.原创 2020-11-05 09:49:18 · 293 阅读 · 0 评论 -
《Fluent Python》读书笔记-2.5
前面学习了元组拆包,用处很多,可以用来多个变量并行赋值、交换数据、调用函数、函数返回值分拆等等。接着思考这样一个问题,如果一个生成器表达式产生不定项的数据,怎么样来进行并行赋值呢?使用星号(*)来接收不定项的赋值在Python的函数里,常常使用*args来接收不定项的函数参数,这是Python的重要编程规则,因此在Python 3以后,也把这个编程规则进行扩展,应用到并行赋值方面:>>> a, b, *rest = range(5)>>> a, b,.原创 2020-11-04 12:19:38 · 352 阅读 · 0 评论 -
《Fluent Python》读书笔记-2.4
元组(tuple)不仅仅是不可改变的列表在很多Python的教材里都是把元组当作不可修改的列表来看待,其实元组不仅如此,还有另外一个大作用,当作没有记录名称的记录数据表示。这种使用方法往往容易被人们忽略它,导致广泛地缺乏认识到它的作用。元组作为记录当你把元组当作记录使用时,元组里每一项当作一个字段,而字段的位置就表示了它的意义。比如(姓名,姓别,学历),这个元组第一项就是表示姓名,所有数据记录必须按照这个顺序来排列。如果你只是把元组当作不变的列表使用时,其实元组里有多少项,或者每项的..原创 2020-11-03 17:31:25 · 341 阅读 · 1 评论 -
《Fluent Python》读书笔记-2.3
接着下来介绍一下怎么样使用列表解析来生成笛卡尔积,其实就是每一项由两个或多个列表的项联组成。如下图所示:笛卡尔积列表解析能从两个或多个列表联合生成笛卡尔积,每一项由每个列表里的项构造,然后保存为一个元组,把这些元组构造成一个列表,这个列表的长度等于所有输入列表长度的乘积。下面的例子:在这里有3种类型和4种花色的牌,可以组成12种结果。接着下来举一个小的例子,假如产生T-shirt有两种颜色和三个尺码,使用列表解析来生成,共有6项:>>> colors..原创 2020-11-03 14:09:59 · 353 阅读 · 0 评论 -
《Fluent Python》读书笔记-2.2
在众多的序列型的容器里,最基本的容器是列表(list),它不仅可修改而且可以昆合不同的数据类型。我相信所有人都学会它的基本操作,但是有点难度的就是列表解析(list comprehension)了。一种强大的构建列表的方法,但由于语法的不熟悉,或不理解,它的作用被低估计了。掌握列表解析就是打开生成表达式的大门,生成表达式在其他用途中,它可以产生元素来填充任何类型的序列。因此通过对比列表解析表达式和生成表达式的方式来理解它们的作用。列表解析(List Comprehensions)和生成表达式(Ge.原创 2020-11-02 11:40:53 · 346 阅读 · 0 评论 -
《Fluent Python》读书笔记-2.1
Python的创建人Guido在创建Python之前,他用了10年的时间在开发一种叫ABC的语言,这种语言是为初学者量身定制。在ABC里定义了很多像目前Python的属性:序列范型操作、内置元组和映射类型、缩进排版结构、没有声明的强类型变量等等。因此,Python对用户这么友好并不是偶然决定的,而是来源于原来ABC语言的一些特性的继承。 Python从ABC语言继承了序列统一操作的习惯,字符串、列表、字节序列、数组、XML元素集和数据库的结果集,都采用一套公共的操作,比如迭代访问、切片、排序和并接...原创 2020-11-01 17:44:02 · 424 阅读 · 0 评论 -
对比学习Python格式化字符串的三种方法(%,format(),f-string)
技术总是随着时代进步而不断地往前推进,也许因为人们对自己的需求不太清楚,也许是由于当时思维模式不对,也许是习惯的力量。在Python的功能里,也是一步一步地往前推进,它的易用性也是一步一步地更方便了。Python 3.6 引入了新的字符串格式化方式 f-string,与其它格式化方式相比,不仅简洁明了,可读性更好,更不容易出错,而且运行效率也更高。你应该马上开始使用这种新的格式化方式,本文将解释其原因与具体用法。但在此之前,让我们先看一下 f-string 之前的字符串格式化方式。 所有编程开发人...原创 2020-11-01 10:11:25 · 873 阅读 · 0 评论 -
Python里变量进行类型备注
众所周知Python是动态语言,变量可以动态地赋值,函数的参数变量也可以动态地改变类型,但是有时候写出下面这样的代码:#学习算法笔记-蔡军生(qq:9073204)#https://mysoft.blog.youkuaiyun.com/#2020-10-30def add(x, y): return x + yprint(add(1,2))print(add(1, 'abc'))突然出现一个错误,让你措手不及,这个错误提示如下:Traceback (most recent call原创 2020-10-31 20:40:34 · 571 阅读 · 0 评论 -
Python从zip文件里导入包
有时候为了节省空间,可以把包压缩成zip文件,这样方便管理,方便上传到网络上,也方便拷贝。但是有没有方法可以直接使用zip文件的包,而不需要解压出来呢?这是有的。 先创建一个目录如下:然后把demo目录使用压缩软件,或者使用Python里的zip模块,就可以生成压缩文件mylib.zip。在目录demo中创建__init__.py文件,然后在文件里输入下面内容:#学习算法笔记-蔡军生(qq:9073204)#https://mysoft.blog.youkuaiyun.com/#2020-1...原创 2020-10-30 19:35:30 · 1289 阅读 · 0 评论 -
Python对于包的使用
随着对Python学习的深入,慢慢就会成长起来,这时薪水也会水高船涨。这是因为你的代码越写越多,积累各种代码模块也越来越多,对于老板布置的任务也越来越得心应手,对于客户提出的要求也越来越随心所欲。一个成长起来的程序员,与初入门的程序员的区别在哪里呢?显然不仅仅是薪水的差别,关键还是能力的差别。当然,能力表现有很多方面,比如处理业务的熟练程度,又或者与同事的配合程度,又或者对公司的流程了如指掌等等。在我认为,一个熟悉程序与入门程序员的最大区别是在于积累。熟练程序之所以这么快完成任务,是因为他的效率比较高,效率原创 2020-10-30 19:16:16 · 254 阅读 · 0 评论 -
Python里__all__变量的作用
在Python的模块里,要想像C语言编写的DLL动态连接库一样,可以提供函数的接口名称,就需要使用__all__变量了。通过这个特性,可以控制哪些函数被外面引用,哪些不能看见。这对一个大工程的软件来说是至关重要,因为没有控制的暴露,会导致别的软件开发人员乱用,从而让软件调用之间出现隐形的问题。比如只给出一个接口的组件,肯定比给出一千个接口的组件使用起来简单。因此,在一个团队的开发配合中,一定要明确这样一条准则:能少不能多,够用就好。把无关重要的接口暴露出来,就会导致更多的问题。__all__ = ['原创 2020-10-30 17:30:23 · 1532 阅读 · 1 评论 -
Python -m abc和Python abc.py的区别
学了一段时间Python语言之后,很多人开始编写复杂的软件,这时代码写在一个文件里,已经不太可能。另外,自己想写所有的功能代码也不太可能了,更何况还有老板的deadline。还有不断地重复地造轮子也不是办法,如果有相同的功能,又可以控制的代码,肯定先用这种方式。这时就需要调用别人的模块组件,在调用别人的模块组件时,也许想测试一下它的功能是否够用。这时候再想使用Python abc.py的方式来运行模块的代码,就比较麻烦了,首先你需要找到模块代码所在目录,另外在那个目录下运行,又会导致很多临时文件产生,以及与原创 2020-10-30 11:07:33 · 826 阅读 · 0 评论 -
Python开发人员常犯的几个重大错误
Python 无疑是当今使用最广泛的编程语言,特别是进入人工智能时代,已经成为人工智能开发的主要语言,甚至小学三年级就已经教学该语言。它之所以如此流行,很大程度上是由于简单的语法和老少皆宜的可读性,这使得它非常容易使用。初学者之所以喜欢 Python,是因为它给人一种感觉就像是用英语写一段伪代码一样。但是,无论你有多么丰富的经验,也无论你已经研究过多少种语言,切换到 Python 并不能保证你能做到平稳过渡。具有面向对象编程背景的开发人员很容易忽略 Python 的常用特性,或者说python范式编程。原创 2020-10-29 16:20:38 · 355 阅读 · 0 评论 -
Python多线程时使用屏障对象
如果你仔细地看了我前面的文章,会发现多线程同步里,有已经介绍了锁和事件对象进行同步,接着下来介绍一个比较不一样的同步对象:屏障(threading.Barrier)。屏障对象在多线程同步中设置一道门,而这扇门有一把锁,需要一定数量的线程到达之后才可以解锁。如果先到的线程,就会等待,直到数量满足。这就好比组织一次旅游,所有游客到达大巴时才会开车出发,不会因为几个人先上车,就让大巴开走。所有人到达大巴的事件,就叫做屏障事件。Barrier(parties, action=None, timeout=N.原创 2020-10-29 10:52:49 · 419 阅读 · 0 评论 -
Python使用事件信号进行线程同步
线程同步除了使用线程锁之外,还可以使用事件信号Event类。为什么要使用事件信号呢?其实从生活中的例子就可以懂得这个道理,比如两个人一起煮饭。一个人洗锅,一个人洗米。如果先洗米的人干活比较快,或者说比较懒,只洗一次米,洗完的米就立即倒到锅里,而另外一个还没有把锅洗干净,这时会发生什么呢?不是给洗锅的人一顿骂,就是一顿打了。因为干净的米,放到不干净的锅,那么最后的结果还是不干净的,相当于白做了工作。所以在生活中,两个一起干活时,肯定会让先洗完米的人等一下,直到洗锅的人把锅刷干净,就不会发生这样的事情了。在多线原创 2020-10-29 09:50:31 · 333 阅读 · 1 评论