• [技术干货] 潘周聃之Python分聃 -----数字雨加入潘周聃运动曲线[转载]
    前言相信各位同学最近一定被潘周聃刷屏和洗脑了,互联网上也出现了这种各样的模仿者,做为思维活跃的IT人,网上冲浪先进分子,以及整活小能手,我们当然也不能落伍,话不多说,整活开始。什么是潘周聃运动曲线首先,这个在曲线在热点时间出现之前是不存在的,这条曲线是博主勇敢di牛牛在总结了潘周聃的起身动作特点后总结出来的。下面详细介绍曲线产生的过程。模型求解:原视频动作分析【潘中单】潘周聃走路⚡️原版上面是原版视频,通过对比其他模仿者的视频,我们可以发现此次热点动作的 核心在于潘同学起身时,身体重心相对于起始轴的偏移首先我们对该动作的重心变化做一个简单的分析:这是普通人可以看到重心一般情况是垂直上升的,并不会突然产生偏移。这是潘同学:当然,这只是一个粗略的轨迹,真正的轨迹有待进一步拟合,要想较好的拟合出运动轨迹,我们需要知道两个参数。相对与主轴的偏移量随时间t的变化:△x = f(t)垂直方向的运动分量:y = f(t)垂直方向运动模型求解:首先是比较简单的垂直方向,在初中我们学习过,人在起立的时候是先加速后减速,设速度为V(t),则y = V(t)t我们暂且先用一个先增后减的函数来模拟速度:假设:V(t) = sin(t),这时聪明的你肯定会说,当 t>π 时速度不就小于0了,总不能再坐回去吧?所以说为了防止它坐回去,我们设起身运动的总时间为T,那么完成起身动作后有:v = 0且t = T,根据三角函数特性我们很容易得出:V ( t ) = s i n ( t π T − 1 ) V(t) = sin(tπT^{-1})V(t)=sin(tπT −1 )不同的身高H对应不同的时间T,所以这里还需要一个常数:设为β则有:H / 2 = ∫ 0 T β s i n ( t π T − 1 ) d t   . H/2 = \int_0^Tβsin(tπT^{-1})dt\,.H/2=∫ 0T​ βsin(tπT −1 )dt.一个很简单的定积分方程,很容易解的:β = H π / 4 T β = Hπ/4Tβ=Hπ/4T所以垂直方向的轨迹我们就暂时搞定:y = V ( t ) t = H π / 4 T ∫ 0 t s i n ( t π T − 1 ) d t   . y = V(t)t = Hπ/4T\int_0^tsin(tπT^{-1})dt\,.y=V(t)t=Hπ/4T∫ 0t​ sin(tπT −1 )dt.而上面的方程也符合我们生活中的一条现象:不同身高的人完成起身动作的时间其实是差不多的因为当y = H/2 时,T与H无关。水平方向运动模型求解:动态不好分析,我们先来看一张图片是不时感觉似曾相识,没错,他和我们的tanX较为相似:这样还不是很直观,没关系,让我们把他倒过来:我们肯定也不能直接用这个函数,需要对他做一下变换,取出我们想要的东西,首先这个函数我们只需要一部分,我们的X是从0开始,所以我们做如下变化:我们取上面的 ∀ x ∈ [ 0 , 9 ] \quad\forall x\in\mathbb [0, 9]∀x∈[0,9]需要注意:这里的y是随X变化,并不是t对其求反函数我们算出相对于X轴的偏移速率,即潘同学重心相对于初始身体轴的偏移速率:得出:Δ X = a r c t a n ( x − 5 ) + 1.4 ΔX = arctan(x - 5) + 1.4ΔX=arctan(x−5)+1.4因为为了方便观察,我们之前去了反函数,这里需要换回去。对应的: ∀ y ∈ [ 0 , 9 ] \quad\forall y\in\mathbb [0, 9]∀y∈[0,9]这里的9是我们的模型终点,即我们起身动作重心的垂直偏移量:得到y m a x = H / 2 y max= H/2ymax=H/2即: ∀ y ∈ [ 0 , H / 2 ] \quad\forall y\in\mathbb [0,H/2]∀y∈[0,H/2]重心的水平偏移量大概为身高的1/4,函数本身已经满足这个特性,我们这里不再考虑。将此模型取一个单位,考虑到身高后的方程为:Δ X = H / 18 a r c t a n ( 18 y / H − 5 ) + 1.4 ΔX = H/18 arctan(18y/H - 5) + 1.4ΔX=H/18arctan(18y/H−5)+1.4有细心同学可能会问这里为什么是18,别忘了我们变换最大区间的时候那个9没了,所以要补偿在这里,才能保持形状不变,这里是初二知识了。模型验证静态验证下面我们使用Python的matplotlib库绘图,对轨迹进行一个验证,import matplotlib.pyplot as pltimport numpy as npdef path(H):    # H是我们测试模型的身高    y = np.arange(0.1, H / 2, 0.1)  # y方向区间    # x = pow((pow(y,2) - 10*y + 26),-1)    x = H / 18 * (np.arctan(18 * y / H - 5) + 1.4)    plt.plot(x, y)    plt.show()path(180)path(90)path(160)制作偏移量生成工具我们知道,数字雨的每一个数字都会在每一帧进行垂直移动,我们只要在想要进行潘周聃曲线的时候插入上面的偏移量即可。原理是上面的这里直接上代码:import numpy as npdef path(H, T, t0):    # H是我们测试模型的身高    listy = []    t = np.arange(0, T, t0)    ys = H * (np.pi) / (4 * T) * np.sin(t * np.pi / T)  # 垂直方向的速度函数    y0 = 0    for i in ys:        s0 = (i + y0) * t0 / 2  # 垂直方向单位时间内移动距离        listy.append(s0)        y0 = i  # 记录前一次的速度    s0 = 0    s = 0    listy0 = []    for i in ys:        s = s + (i+s0) * t0 / 2  # 垂直总路程        listy0.append(s)        s0 = i    y = np.array(listy0)    x = H / 18 * (np.arctan(18 * y / H - 5) + 1.4)    x0 = 0    listx = []    for i in x:        s0 = i - x0  # 水平方向单位时间内移动距离        listx.append(s0)        x0 = i  # 保存前一次的X坐标    return listx, listyprint(path(100,5,0.1))数字雨效果制作哈哈哈,到这里我们的数字雨就变得妖娆起来啦,是不是有潘周耼的风范呢了,上代码:import pygameimport random# !/usr/bin/env python3# -*- coding: utf-8 -*-# @Date  : 2018/10/23import numpy as npimport randomimport pygamedef path(H, T, t0):    # H是我们测试模型的身高    listy = []    t = np.arange(0, T, t0)    ys = H * (np.pi) / (4 * T) * np.sin(t * np.pi / T)  # 垂直方向的速度函数    y0 = 0    for i in ys:        s0 = (i + y0) * t0 / 2  # 垂直方向单位时间内移动距离        listy.append(s0)        y0 = i  # 记录前一次的速度    s0 = 0    s = 0    listy0 = []    for i in ys:        s = s + (i + s0) * t0 / 2  # 垂直总路程        listy0.append(s)        s0 = i    y = np.array(listy0)    x = H / 18 * (np.arctan(18 * y / H - 5) + 1.4)    x0 = 0    listx = []    for i in x:        s0 = i - x0  # 水平方向单位时间内移动距离        listx.append(s0)        x0 = i  # 保存前一次的X坐标    return listx, listyPANEL_width = 600PANEL_highly = 500FONT_PX = 15pygame.init()# 创建一个可视化窗口winSur = pygame.display.set_mode((PANEL_width, PANEL_highly))font = pygame.font.SysFont("123.ttf", 25)bg_suface = pygame.Surface((PANEL_width, PANEL_highly), flags=pygame.SRCALPHA)pygame.Surface.convert(bg_suface)bg_suface.fill(pygame.Color(0, 0, 0, 28))# winSur.fill((0, 0, 0))# 数字版# letter = [font.render(str(i), True, (0, 255, 0)) for i in range(10)]# 字母版letter = ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c',          'v', 'b', 'n', 'm']texts = [    font.render(str(letter[i]), True, (0, 255, 0)) for i in range(26)]# 按屏幕的宽带计算可以在画板上放几列坐标并生成一个列表column = int(PANEL_width / FONT_PX)drops = [0 for i in range(column)]print(drops)pan = -1x0 = 0y0 = 0i0 = 0dropsx = [0 for i in range(column)]dropsy = [0 for i in range(column)]listx, listy = path(400, 2, 0.1)kk = 0  # 获取之前的坐标finsh = Falseallfinish =Falsewhile True:    # 从队列中获取事件    for event in pygame.event.get():        if event.type == pygame.QUIT:            exit()        elif event.type == pygame.KEYDOWN:            chang = pygame.key.get_pressed()            if chang[32]:  # 按下空格键                pan = 1000                i0 = 5   # 取消密集点    if pan > 0:        pygame.time.delay(100)        winSur.blit(bg_suface, (0, 0))        pan = pan - 1        if i0 < len(listx):            x0 = listx[i0]            y0 = listy[i0]        else:            finsh = True        i0 = i0 + 1        if kk == 0:            for i in range(len(drops)):                dropsx[i] = i * FONT_PX                dropsy[i] = drops[i] * FONT_PX            kk = 1        if finsh:            allfinish = True            for i in range(len(drops)):                text = random.choice(texts)                dropsy[i] = dropsy[i] + FONT_PX                dropsx[i] = dropsx[i]                # 重新编辑每个坐标点的图像                winSur.blit(text, (dropsx[i], dropsy[i]))                if dropsy[i] > PANEL_highly and allfinish:  # 到头了                    allfinish = True                else:                    allfinish =False        for i in range(len(drops)):            text = random.choice(texts)            dropsy[i] = dropsy[i] + y0            dropsx[i] = dropsx[i] + x0            # 重新编辑每个坐标点的图像            winSur.blit(text, (dropsx[i], dropsy[i]))            # if drops[i] * 10 > PANEL_highly:  # 到头了,或者运气不好            # drops[i] = 0        if allfinish:            pan = -1            drops = [0 for i in range(column)]            pygame.display.flip()            dropsx = [0 for i in range(column)]            dropsy = [0 for i in range(column)]            finsh = False            allfinish = False            kk = 0            continue        pygame.display.flip()        continue    # 将暂停一段给定的毫秒数    pygame.time.delay(100)    # 重新编辑图像第二个参数是坐上角坐标    winSur.blit(bg_suface, (0, 0))    for i in range(len(drops)):        text = random.choice(texts)        # 重新编辑每个坐标点的图像        winSur.blit(text, (i * FONT_PX, drops[i] * FONT_PX))        drops[i] += 1  # 向下走一格        if drops[i] * 10 > PANEL_highly or random.random() > 0.98:  # 到头了,或者运气不好            drops[i] = 0    pygame.display.flip()== 我设置的是按下空格键之后进行潘化,跑完自动复原。==声明以上内容纯属娱乐,以及为了表达对潘周聃同学的仰慕。如有疑问请留言或私信博主。原文链接:https://blog.csdn.net/niuguobao/article/details/124642608
  • [技术干货] python 数据分析异常检测anomaly detection[转载]
    链接:https://bbs.huaweicloud.com/blogs/3525791 正确率检验分布使用正确率和召回率进行检验 (2.0precisionrecall)/(precision+recall)def F1(predictions,y): TP=np.sum((predictions==1)&(y==1)) FP=np.sum((predictions==1)&(y==0)) FN=np.sum((predictions==0)&(y==1)) if (TP+FP)==0: precision=0 else: precision=float(TP)/(TP+FP) if (TP+FN)==0: recall=0 else: recall=float(TP)/(TP+FN) if precision+recall==0: return 0 else: return (2.0*precision*recall)/(precision+recall)2 普通正态分布概率密度函数def gaussianModel(X): #参数估计 m,n=X.shape mu=np.mean(X,axis=0) sigma2=np.var(X,axis=0) def p(x):#x是单个样本,n*1维 total=1 for j in range(x.shape[0]): total*=np.exp(-np.power((x[j,0]-mu[0,j]),2)/(2*sigma2[0,j]))/(np.sqrt(2*np.pi*sigma2[0,j])) return total return p3 相关正态分布概率密度函数特征变量之间可能存在相关性def multivariateGaussianModel(X): #参数估计 m,n=X.shape mu=np.mean(X.T,axis=1) sigma=np.mat(np.cov(X.T)) detSigma=np.linalg.det(sigma) def p(x): x=x-mu return np.exp(-x.T*np.linalg.pinv(sigma)*x/2).A[0]*((2*np.pi)**(-n/2.0)*(detSigma**(-0.5))) return p4 模型选择于epsilon残差选择def train(X,model=gaussianModel):return model(X) #返回的是概率模型pdef selectEpsilon(XVal,yVal,p): pVal=np.mat([p(x.T) for x in XVal]).reshape(-1,1)#交叉验证集中所有样本的概率 step=(np.max(pVal)-np.min(pVal))/1000.0 bestEpsilon=0 bestF1=0 for epsilon in np.arange(np.min(pVal),np.max(pVal),step): predictions=pVal<epsilon f1=F1(predictions,yVal) if f1>bestF1: bestF1=f1 bestEpsilon=epsilon return bestEpsilon,bestF1返回残差选择值能使F1最大的值5 读取数据准备%matplotlib inlinefrom scipy.io import loadmatimport matplotlib.pyplot as plpl.rcParams[‘font.sans-serif’]=‘SimHei’ #画图正常显示中文pl.rcParams[‘axes.unicode_minus’]=False #决绝保存图像是负号‘-’显示方块的问题def loadDataset(filename): X=[] Y=[] with open(filename,'rb') as f: for idx,line in enumerate(f): line=line.decode('utf-8').strip() if not line: continue eles=line.split(',') if idx==0: numFea=len(eles) eles=list(map(float,eles))#map返回一个迭代对象 X.append(eles[:-1]) Y.append([eles[-1]]) return np.array(X),np.array(Y)#低维数据测试ori_X,ori_y=loadDataset(’./data/gender_predict.csv’)m,n=ori_X.shapeX=np.mat(ori_X[40:100])y=np.mat(ori_y[40:100])XVal=np.mat(ori_X[20:40])yVal=np.mat(ori_y[20:40])Xtest=np.mat(ori_X[0:20])ytest=np.mat(ori_y[0:20])6 检验绘图p=train(X) #p=train(X,model=multivariateGaussianModel) pTest=np.mat([p(x.T) for x in X]).reshape(-1,1) #绘制数据点 pl.xlabel(u'年龄') pl.ylabel(u'收入') pl.plot(X[:,0],X[:,1],'bx') epsilon,f1=selectEpsilon(XVal,yVal,p) print(u'基于交叉验证集最佳ε: %e\n'%epsilon) print(u'基于交叉验证集最佳F1: %f\n'%f1) print(u'找到%d个异常点'%np.sum(pTest<epsilon)) #获得训练集的异常点 outliers=np.where(pTest<epsilon,True,False).ravel() pl.plot(X[outliers,0],X[outliers,1],'ro',lw=2,markersize=10,fillstyle='none',markeredgewidth=1) n=np.linspace(0,60,100) X1=np.meshgrid(n,n) XFit=np.mat(np.column_stack((X1[0].T.flatten(),X1[1].T.flatten()))) pFit=np.mat([p(x.T) for x in XFit]).reshape(-1,1) pFit=pFit.reshape(X1[0].shape) if not np.isinf(np.sum(pFit)): pl.contour(X1[1],X1[0],pFit,10.0**np.arange(-6,0,3).T) pl.show()使用交叉验证集选择的超惨epsilon进行异常值检验,绘图标注训练集发现较好的把数据进行了检测7 使用有相关性的检验只改了第一行的代码,将p使用的模型进行了更改#p=train(X) p=train(X,model=multivariateGaussianModel) pTest=np.mat([p(x.T) for x in X]).reshape(-1,1) #绘制数据点 pl.xlabel(u'年龄') pl.ylabel(u'收入') pl.plot(X[:,0],X[:,1],'bx') epsilon,f1=selectEpsilon(XVal,yVal,p) print(u'基于交叉验证集最佳ε: %e\n'%epsilon) print(u'基于交叉验证集最佳F1: %f\n'%f1) print(u'找到%d个异常点'%np.sum(pTest<epsilon)) #获得训练集的异常点 outliers=np.where(pTest<epsilon,True,False).ravel() pl.plot(X[outliers,0],X[outliers,1],'ro',lw=2,markersize=10,fillstyle='none',markeredgewidth=1) n=np.linspace(0,60,100) X1=np.meshgrid(n,n) XFit=np.mat(np.column_stack((X1[0].T.flatten(),X1[1].T.flatten()))) pFit=np.mat([p(x.T) for x in XFit]).reshape(-1,1) pFit=pFit.reshape(X1[0].shape) if not np.isinf(np.sum(pFit)): pl.contour(X1[1],X1[0],pFit,10.0**np.arange(-6,0,3).T) pl.show()l
  • [互动交流] 【WeAutomate华为RPA】【Python版本】基于WeAutomate Python为3.9是否可自己降低py版本?
    请问,目前我使用的是华为RPA 3.0的 设计器,里面集成的是python3.9的版本,但是我们的服务器是win server2008r2的,查阅了一下py3.9好像不在支持该操作系统版本,于是我想自行降低python的版本。。请问可以这样做么? 如果可以的话,受累咨询下,如何降低py的版本
  • [培训赋能] weautomate_如何学习
    > 之前粗略的看了一遍weautomate,并没有实际使用。因缘际会,有需要使用一阵weautomate来支撑一些业务。不可避免的需要再学习。新一轮的学习,需要仔细一些了,如何学便成为了一个问题?下面可能是几个很好的方式,互补最佳吧。 ##### 看官网的给出的学习课程 > 掌握基础概念 官网的链接 https://education.huaweicloud.com/programs/a0d1e0a7-e78f-4525-b963-a6e92f2cba89/about 官网的学习路径分初中高三个等级,涵盖了各个方面,但都是很基础的东西.人性化的是在基础教学中有各种的例子和对应的源码。 ##### 对标理解 > 类比熟悉 weautomate中的很多东西和python的概念接近,如果熟悉Python可以直接对标理解相应的功能。 ##### 从模板新建 > 看别人的代码 在weautomate studio 中的有各种各样的模板,是别人写好的代码,也就是基于此去二开。看看别人的代码,取其精华去其糟泊。 如果有机会和别人一起写,可以借鉴别人的思路....(真TMD的无耻) ##### 实践 > 一个字 练 不言而喻,多写多练多接触各种场景。可以参加weautomate论坛中的各种活动 论坛链接:https://bbs.huaweicloud.com/forum/forum-1407-1.html 也可以参加weautomate的考试,只不过这个考试的费用有点高... 也可以参与实际或者虚拟的项目... ##### 更新 > 保持和官方的联系 比如参加线上培训啊 比如在官方群讨论啊 比如在论坛总结心得啊 诸如此类
  • [技术干货] weautomate_变量和数据类型
    #### 数据类型 > weautomate的数据类型遵循python的数据类型。 在weautomate的变量类型下拉框中有String,Array,Boolean,Number,Object,Attachement,Credential,Sensitive几个变量类型 ##### 类型对标 > Object 在weautomate中的object对标的python中的dictionary 在对dict进行循环的时候可以用@{dictvarname}.items()/@{dictvarname} 前者给出的是key/value,后者给出的是key **在weautomate中dict的取值使用的心得控件叫做:getObjectValue** > Array 在weautomate中的array对标的python中的list > String 在weautomate中的string对标的是python中的string > Number 在weautomate中的number对标的不知道是float/int/double中的哪个或许是所有把 > Datetime 在weautomate中的datetime对标的是python中的datetime。可能是使用的频率不高的原因datetime并没有加入到变量类型的下拉框中,反而形成了几个特定的控件。 **时间处理分组中的控件** * 获取当前时间 getCurrentTime * 时间转时间戳 datetime.timestamp * 时间戳转时间 datetime.localtime #### 作用域 > 这里有两个新概念 全局变量fx 和全局参数 全局变量对标的是局部变量 全局参数对标的是global变量 #### 运行python表达式/eval 顾名思义就是对python中的eval函数调用,并在使用前对变量进行了相应的替换.
  • [技术干货] weautomate_python第三方包管理和使用
    #### 安装第三方库 首先定位到weautomate的python安装文件夹中,进入控制台, 输入命令: > Robot -m pip install xpinyin 即可完成对第三方库 xpinyin的安装 ``` Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple/ Collecting xpinyin Downloading https://pypi.tuna.tsinghua.edu.cn/packages/ a5/30/40e099a8da32105c8adf996abe92a5bbf5ecd338de2c4cc491b5718299ce/xpinyin-0.7.6-py3-none-any.whl (129 kB) |████████████████████████████████| 129 kB 1.7 MB/s Installing collected packages: xpinyin Successfully installed xpinyin-0.7.6 ``` #### 查看第三方库 还是优先定位到weautomate的python安装文件夹,进入控制台, 输入命令 > Robot -m pip list | findstr xpinyin ``` xpinyin 0.7.6 ``` #### 调用第三方库 将写完的python插件放到项目的根目录下 在调用控件里使用pyexe来执行即可 #### 卸载第三方库 > Robot -m pip uninstall xpinyin ``` Found existing installation: xpinyin 0.7.6 Uninstalling xpinyin-0.7.6: Would remove: d:\soft\huawei\weautomate\studio 3.0.0\python\lib\site-packages\xpinyin-0.7.6.dist-info\* d:\soft\huawei\weautomate\studio 3.0.0\python\lib\site-packages\xpinyin\* Proceed (Y/n)? y Successfully uninstalled xpinyin-0.7.6 ``` #### 离线安装 需要在外网环境下,下载对应的安装包 > pip download xpinyin -d . 在将安装包拷贝到内网环境下安装 > Robot -m pip install --no-index --find-links="C:\Users\zealone\Desktop\package" xpinyin ``` Looking in links: c:\Users\zealone\Desktop\package Processing c:\users\zealone\desktop\package\xpinyin-0.7.6-py3-none-any.whl Installing collected packages: xpinyin Successfully installed xpinyin-0.7.6 ``` #### 总结 weautomate的python库管理套用的是pip的壳,只是需要在前面加一个 > Robot -m 然后正常使用pip 的相关命令即可 #### 补充 > 内容来源于论坛 当前设计器与执行器「2.1.8以及3.0版本」自带的python环境对于python三方库的 加载先后顺序是: 1、优先加载设计器执行器系统自带的库 2、其次加载用户工程目录\Lib文件夹里的库 优化后的加载顺序为: 优先加载用户工程目录\Lib文件夹里的库 其次加载设计器执行器系统自带的库 **这样只需要把自己用到的库放到工程目录\Lib文件夹,便可以不依赖设计器或者执行器的环境来运行。** > QA 那如何给用户工程目录的Lib库里更新内容呢?需要手动增加依赖吗?
  • [技术干货] python之future对象-利用自定义函数、遍历来实现搜索~
    我们都知道future对象来实现的是并发操作,future根据我们的需求的并发类型(I/O密集型,或是cpu密集型)打包了multiprocessing和threading。它们并不能完全解决以外修改共享的问题,但却帮助我们更容易地追踪这一问题。Future为不同进程或进程间提供了明确的边界。和多进程池类似 他们用于调用并回答 类型的交互 其中处理过程可以在另外一个进程中,并且在未来的某个节点(毕竟就是这样命名的),你可以询问结果向他。Future实际上就是对进程池和线程池的封装,不过它提供了更加清楚的API。Future对象基本上封装了一个函数调用。函数调用进行在线程或进程的后台。Future对象的方法检查future是否结束,并在结束后获取结果。例子:From concurrent.futures import threadpoolexecutorFrom pathlib import pathFrom os.path import sep as pathsepFrom collections import dequeDef find _files(path,query_string):Subdirs=[]For p in path.iterdir():   Full_path = str(p.absolute())   If p.is_dir() and not p.is_symlink():      Subdirs.append(p)   If query_string in full_path:     Print(full_path)   Return subdirsQuery = ‘.py’Futures = deque()Basedir = path(pathsep).absolute()With threadpoolexecutor(max_workers=10) as executor:Futures.append(Executor.submit(find_files,basedir,query))While futures:Futures=futures.popleft()If futures.exeception():ContinueElif futere,done():Subdirs=future.result()For subdir in subdirs:   Futures.append(executor.submit(                Find_files,subdir,query))Else:   Futures.append(future)这段代码是由find_files的函数组成  运行在另外一个线程中 这个函数没有其他的特殊地方但是要注意他访问全局变量的过程,我们在开始之前先定义几个变量,在这个例子中我们会搜索所有带.py字符的文件我们有一个队列的future对象 稍后进行讨论  basedir变量指向文件系统的根目录 unnix系统中的是’/’windows系统中的是C:\.我们简单回顾下搜索的理论是什么,这一算是通过广度优先搜索遍历来实现的 而不是用深度优先搜索遍历实现的访问所有的路径 这一算法将所有当前目录的子目录添加到队列中 然后是所有这些目录的子目录来类推这段程序的主体是一个事件的循环 我们可以将 threadpoolexecutor构建为一个上下文管理器,这样一来在结束时就可以进行自动清理关闭所有的进程,需要一个max_workers参数来表明同时允许执行多个线程 如果提交了超过这一数量的任务将会排队等待 直到有能用的线程出现为止。在使用processpoolexecutor时 这一限制通常为机器的cpu数量 但对于线程 这一数值可以高很高 这依赖于同时等待i/o的数量。每个线程都需要占据一定的内存因此数量也不需要很多,数量太多的话磁盘速度而不是并发请求数量将会成为瓶颈
  • [热门活动] 【华为云AI证书和手机待领取】DevRun AI应用开发Python实战营
    【报名福利】报名后即可参与抽奖,超5%中奖概率,抽华为畅享10 Plus手机、华为路由器、华为nova mini蓝牙音箱、华为云AI定制衣服、定制保温杯!【活动亮点】0门槛入门Python,华为名师从环境搭建开始带您走进Python的世界,了解Python独特的语法,同时结合实践操作,增强您的编程能力。>>> 点击报名链接<<<【活动流程】①报名加入学习群,②在线课程,③实践案例直播课,④结业颁奖 ①【加入学习群】扫码添加小助手,加入学习群↓↓↓↓↓②【在线课程】总分500分开发者完成以下三门课程的进度和测试,可获得对应的分数。· 华为名师揭秘编程界“网红”Python:· Python入门篇:· Python进阶篇: ③【实践案例直播课】总分100分老师保姆式教学,完成实践案例可获得对应的分数:④【结业颁奖】获得满分600分的开发者,活动结束后将获得由华为云AI颁发的【DevRun AI应用开发-Python实战营结业证书】【邀请报名奖励】>>> 点击报名链接<<<>>> 点击报名链接<<<【活动说明】①请务必使用个人实名账号参与活动(IAM、企业账号等账号参与无效)。②为保证活动的公平公正,华为云有权对恶意刷活动资源(“恶意”是指为获取资源而异常注册账号等**活动公平性的行为,黑产用户不计入活动统计),利用资源从事违法违规行为的用户收回奖励资格,本次活动一个实名认证账号只能对应一个收件人(只能参加一次),如同一账号填写多个不同收件人,不予发放奖励,且每个账号只记录最早的一次回帖,多发无效。排名奖项若有并列,按照完成时间先后顺序排列。③本活动规则由华为云在法律规定范围内进行解释。华为云保留不时更新、修改或删除本活动规则的权利。上述更新、修改或删除于公布时即时生效,用户应当主动查阅本活动规则的最新内容。④所有参加本活动的用户,均视为认可并同意遵守《华为云用户协议》,包括以援引方式纳入《华为云用户协议》的《可接受的使用政策》、《法律声明》、《隐私政策声明》、相关服务等级协议(华为ModelArts服务声明、SLA等),以及华为云服务网站规定的其他协议和政策(统称为“云服务协议”)的约束。如果您不同意本活动规则和云服务协议的条款,请勿参加本活动。
  • [技术干货] 【2.1.8以及3.0版本】设计器与执行器自带的python环境对于python三方库的加载
    当前设计器与执行器「2.1.8以及3.0版本」自带的python环境对于python三方库的加载先后顺序是:1、优先加载设计器执行器系统自带的库2、其次加载用户工程目录\Lib文件夹里的库优化后的加载顺序为:优先加载用户工程目录\Lib文件夹里的库其次加载设计器执行器系统自带的库这样只需要把自己用到的库放到工程目录\Lib文件夹,便可以不依赖设计器或者执行器的环境来运行。如果2.1.8以及3.0版本用户自有的库与设计器执行器环境里的库有冲突的时候,请手动删除系统环境下的路路径为设计器与执行器的安装目录\Python\Lib\site-packages附件为常用的库(在工程需要时按需使用即可)PyMuPDF-1.17.7------pdfToImage控件需要使用xlrd-1.2.0-------可以读写xlsx文件的库(2.0版本只能读取xls文件)
  • [技术干货] 来体验下python代码带给你的编程体验~【原创】
    最火的编程语言python多次上榜 今天给大家分析几个python小程序1:Python小游戏实际分析:猜数游戏:猜数字是一个古老的密码破译的益智类小游戏 通常又俩人及以上人去参与,一个人设置一个数字一个人或多人猜 当猜数字的人说出一个数字时 由出数字的人告知是否猜中;若猜大了应该给予相应的提示比如:猜小了,若猜小了应该给予相应的提示比如:猜大了。猜的数字等于电脑的随机数字应提示:恭喜您 猜数成功代码:import randomprint("猜数字游戏,输入一个1-100以内的数字")random_num = random.randint(1, 100)# print(random_num)  # 打开注释可查看生成的随机数for frequency in range(1,6):    number = input("请输入一个数字:")    if number.isdigit() is False:        print('请输入一个正确的数字')    elif int(number) < 0 or int(number) > 100:        print("请输入1-100范围的数字")    elif random_num == int(number):        print("恭喜你用了%d次猜对了" % frequency)        break    elif random_num > int(number):        print("很遗憾,你猜小了")    else:        print("很遗憾,你猜大了")    if frequency == 5:        print("很遗憾,%d次机会已用尽,游戏结束,答案为%d" %              (frequency, random_num))2:叫⑦   当代年轻人最喜欢的游戏叫⑦游戏规则:每次到啊7或7的倍数的数字就需要拍手如果数了就需要又相应的惩罚:思考:我们需要不断的从1-101进行遍历读取每一个数,判断条件是否包含7是不是7的的倍数这四种可能代码:for i in range(1, 101):     # 把i转成字符串,使用find方法(字符串中不包含时,返回-1)     include = str(i).find("7")     # 判断条件:既不包含7,也不是7的倍数     if include == -1 and int(i) % 7 != 0:         # 输出,去掉了换行符,加了、         print(i, end="、")         # 如果包含7 输出*     elif include != -1 or int(i) % 7 == 0:         print("*", end='、')3:数据加密有没有小伙伴很好奇当年他们用电台去传电报是怎么实现翻译的又衍生了摩斯密码其实每一个代码都对应一个解码比如我们现在输入在电脑的内容都是二进制编程的生活中也有比如 12进制,10进制都需要转换成对应的我们所需要的进制进行翻译才能成功破解思考:ASCLL是什么对ASCLL理解代码:raw_data = input('请输入密码:') num_asc = 0   # ASCII累加值 str_pwd = ''  # ASCII拼接值 for i in raw_data:     ascii_val = ord(i)              # 1.获取每个元素的ASCII值     num_asc = ascii_val + num_asc   # 2.对遍历的ASCII值进行累加操作     str_pwd += str(ascii_val)       # 3.拼接操作     reversal_num = str_pwd[::-1]    # 4.将拼接的ASCII值倒序排列     encryption_num = int(reversal_num) + num_asc  # 5.进行运算操作 print(f"加密后的密码为:{encryption_num}")
  • [工具链] 【MDC300f产品】制作mini镜像
    【功能模块】【操作步骤&问题现象】1、mini端python版本,以及第三方库不符合要求,怎么在mini端镜像中打包特定版本的python以及安装python三方库。【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] Python实现自动玩贪吃蛇
    没装软件的先安装一下软件,没装模块的安装一下pygame模块。pip install pygame导入模块import pygame,sys,time,randomfrom pygame.locals import *定义颜色变量redColour = pygame.Color(255,0,0)blackColour = pygame.Color(0,0,0)whiteColour = pygame.Color(255,255,255)greenColour = pygame.Color(0,255,0)headColour = pygame.Color(0,119,255)在所有后续的除法中,为预防pygame输出出现偏差,必须取除数(//)而不是单纯除法(/)程序界面第0行,HEIGHT行,第0列,WIDTH列为围墙,所以实际大小是13*13IGHT = 15WIDTH = 15FIELD_SIZE = HEIGHT * WIDTH# 蛇头位于snake数组的第一个元素HEAD = 0用数字代表不同的对象,因为运动时矩阵上每个格子会处理成到达食物的路径长度,因此这三个变量间需要有足够大的间隔(>HEIGHT*WIDTH)来互相区分,小写一般是坐标,大写代表常量。FOOD = 0UNDEFINED = (HEIGHT + 1) * (WIDTH + 1)SNAKE = 2 * UNDEFINEDsnake是一维数组,对应元素直接加上以下值就表示向四个方向移动。LEFT = -1RIGHT = 1UP = -WIDTH # 一维数组,所以需要整个宽度都加上才能表示上下移动。DOWN = WIDTH 错误码ERR = -2333用一维数组来表示二维的东西,board表示蛇运动的矩形场地,初始化蛇头在(1,1)的地方,初始蛇长度为1。board = [0] * FIELD_SIZE #[0,0,0,……]snake = [0] * (FIELD_SIZE+1)snake[HEAD] = 1*WIDTH+1snake_size = 1与上面变量对应的临时变量,蛇试探性地移动时使用。tmpboard = [0] * FIELD_SIZEtmpsnake = [0] * (FIELD_SIZE+1)tmpsnake[HEAD] = 1*WIDTH+1tmpsnake_size = 1food:食物位置初始在(4, 7),best_move: 运动方向。food = 4 * WIDTH + 7best_move = ERR运动方向数组,游戏分数(蛇长)mov = [LEFT, RIGHT, UP, DOWN]                                           score = 1 检查一个cell有没有被蛇身覆盖,没有覆盖则为free,返回true 。def is_cell_free(idx, psize, psnake):    return not (idx in psnake[:psize]) 检查某个位置idx是否可向move方向运动def is_move_possible(idx, move):    flag = False    if move == LEFT:        #因为实际范围是13*13,[1,13]*[1,13],所以idx为1时不能往左跑,此时取余为1所以>1        flag = True if idx%WIDTH > 1 else False    elif move == RIGHT:        #这里的<WIDTH-2跟上面是一样的道理        flag = True if idx%WIDTH < (WIDTH-2) else False    elif move == UP:        #这里向上的判断画图很好理解,因为在[1,13]*[1,13]的实际运动范围外,还有个        #大框是围墙,就是之前说的那几个行列,下面判断向下运动的条件也是类似的        flag = True if idx > (2*WIDTH-1) else False    elif move == DOWN:        flag = True if idx < (FIELD_SIZE-2*WIDTH) else False    return flag重置boardboard_BFS后,UNDEFINED值都变为了到达食物的路径长度。如需要还原,则要重置它。def board_reset(psnake, psize, pboard):    for i in range(FIELD_SIZE):        if i == food:            pboard[i] = FOOD        elif is_cell_free(i, psize, psnake): # 该位置为空            pboard[i] = UNDEFINED        else: # 该位置为蛇身            pboard[i] = SNAKE广度优先搜索遍历整个board,计算出board中每个非SNAKE元素到达食物的路径长度。def board_BFS(pfood, psnake, pboard):    queue = []    queue.append(pfood)    inqueue = [0] * FIELD_SIZE    found = False    # while循环结束后,除了蛇的身体,    # 其它每个方格中的数字为从它到食物的曼哈顿间距    while len(queue)!=0:         idx = queue.pop(0)#初始时idx是食物的坐标         if inqueue[idx] == 1: continue        inqueue[idx] = 1        for i in range(4):#左右上下            if is_move_possible(idx, mov[i]):                if idx + mov[i] == psnake[HEAD]:                    found = True                if pboard[idx+mov[i]] < SNAKE: # 如果该点不是蛇的身体                    if pboard[idx+mov[i]] > pboard[idx]+1:#小于的时候不管,不然会覆盖已有的路径数据。                        pboard[idx+mov[i]] = pboard[idx] + 1                    if inqueue[idx+mov[i]] == 0:                        queue.append(idx+mov[i])    return found从蛇头开始,根据board中元素值,从蛇头周围4个领域点中选择最短路径。def choose_shortest_safe_move(psnake, pboard):    best_move = ERR    min = SNAKE    for i in range(4):        if is_move_possible(psnake[HEAD], mov[i]) and pboard[psnake[HEAD]+mov[i]]<min:          #这里判断最小和下面的函数判断最大,都是先赋值,再循环互相比较            min = pboard[psnake[HEAD]+mov[i]]            best_move = mov[i]    return best_move检查是否可以追着蛇尾运动,即蛇头和蛇尾间是有路径的,为的是避免蛇头陷入死路。虚拟操作,在tmpboard,tmpsnake中进行。def is_tail_inside():    global tmpboard, tmpsnake, food, tmpsnake_size    tmpboard[tmpsnake[tmpsnake_size-1]] = 0 # 虚拟地将蛇尾变为食物(因为是虚拟的,所以在tmpsnake,tmpboard中进行)    tmpboard[food] = SNAKE # 放置食物的地方,看成蛇身    result = board_BFS(tmpsnake[tmpsnake_size-1], tmpsnake, tmpboard) # 求得每个位置到蛇尾的路径长度    for i in range(4): # 如果蛇头和蛇尾紧挨着,则返回False。即不能follow_tail,追着蛇尾运动了        if is_move_possible(tmpsnake[HEAD], mov[i]) and tmpsnake[HEAD]+mov[i]==tmpsnake[tmpsnake_size-1] and tmpsnake_size>3:            result = False    return result让蛇头朝着蛇尾运行一步,不管蛇身阻挡,朝蛇尾方向运行。def follow_tail():    global tmpboard, tmpsnake, food, tmpsnake_size    tmpsnake_size = snake_size    tmpsnake = snake[:]    board_reset(tmpsnake, tmpsnake_size, tmpboard) # 重置虚拟board    tmpboard[tmpsnake[tmpsnake_size-1]] = FOOD # 让蛇尾成为食物    tmpboard[food] = SNAKE # 让食物的地方变成蛇身    board_BFS(tmpsnake[tmpsnake_size-1], tmpsnake, tmpboard) # 求得各个位置到达蛇尾的路径长度    tmpboard[tmpsnake[tmpsnake_size-1]] = SNAKE # 还原蛇尾    return choose_longest_safe_move(tmpsnake, tmpboard) # 返回运行方向(让蛇头运动1步)在各种方案都不行时,随便找一个可行的方向来走(1步)def any_possible_move():    global food , snake, snake_size, board    best_move = ERR    board_reset(snake, snake_size, board)    board_BFS(food, snake, board)    min = SNAKE    for i in range(4):        if is_move_possible(snake[HEAD], mov[i]) and board[snake[HEAD]+mov[i]]<min:            min = board[snake[HEAD]+mov[i]]            best_move = mov[i]    return best_move转换数组函数def shift_array(arr, size):    for i in range(size, 0, -1):        arr[i] = arr[i-1]def new_food():#随机函数生成新的食物    global food, snake_size    cell_free = False    while not cell_free:        w = random.randint(1, WIDTH-2)        h = random.randint(1, HEIGHT-2)        food = WIDTH*h + w        cell_free = is_cell_free(food, snake_size, snake)    pygame.draw.rect(playSurface,redColour,Rect(18*(food//WIDTH), 18*(food%WIDTH),18,18))真正的蛇在这个函数中,朝pbest_move走1步。def make_move(pbest_move):    global snake, board, snake_size, score    shift_array(snake, snake_size)    snake[HEAD] += pbest_move    p = snake[HEAD]    for body in snake:#画蛇,身体,头,尾      pygame.draw.rect(playSurface,whiteColour,Rect(18*(body//WIDTH), 18*(body%WIDTH),18,18))    pygame.draw.rect(playSurface,greenColour,Rect(18*(snake[snake_size-1]//WIDTH),18*(snake[snake_size-1]%WIDTH),18,18))    pygame.draw.rect(playSurface,headColour,Rect(18*(p//WIDTH), 18*(p%WIDTH),18,18))    #下面一行是把初始情况会出现的第一个白块bug填掉    pygame.draw.rect(playSurface,(255,255,0),Rect(0,0,18,18))    # 刷新pygame显示层    pygame.display.flip()         # 如果新加入的蛇头就是食物的位置    # 蛇长加1,产生新的食物,重置board(因为原来那些路径长度已经用不上了)    if snake[HEAD] == food:        board[snake[HEAD]] = SNAKE # 新的蛇头        snake_size += 1        score += 1        if snake_size < FIELD_SIZE: new_food()    else: # 如果新加入的蛇头不是食物的位置        board[snake[HEAD]] = SNAKE # 新的蛇头        board[snake[snake_size]] = UNDEFINED # 蛇尾变为UNDEFINED,黑色        pygame.draw.rect(playSurface,blackColour,Rect(18*(snake[snake_size]//WIDTH),18*(snake[snake_size]%WIDTH),18,18))        # 刷新pygame显示层        pygame.display.flip() 如果蛇与食物间有路径,则调用本函数。def find_safe_way():    global snake, board    safe_move = ERR    # 虚拟地运行一次,因为已经确保蛇与食物间有路径,所以执行有效    # 运行后得到虚拟下蛇在board中的位置,即tmpboard    virtual_shortest_move() # 该函数唯一调用处    if is_tail_inside(): # 如果虚拟运行后,蛇头蛇尾间有通路,则选最短路运行(1步)        return choose_shortest_safe_move(snake, board)    safe_move = follow_tail() # 否则虚拟地follow_tail 1步,如果可以做到,返回true    return safe_move初始化pygame 模块pygame.init()定义一个变量用来控制游戏速度fpsClock = pygame.time.Clock()创建pygame显示层playSurface = pygame.display.set_mode((270,270))pygame.display.set_caption('贪吃蛇')绘制pygame显示层playSurface.fill(blackColour)初始化食物pygame.draw.rect(playSurface,redColour,Rect(18*(food//WIDTH), 18*(food%WIDTH),18,18))while True:    for event in pygame.event.get():#循环监听键盘和退出事件        if event.type == QUIT:#如果点了关闭            print(score)#游戏结束后打印分数            pygame.quit()            sys.exit()        elif event.type == KEYDOWN:#如果esc键被按下            if event.key==K_ESCAPE:                print(score)#游戏结束后打印分数                pygame.quit()                sys.exit()    # 刷新pygame显示层    pygame.display.flip()      #画围墙,255,255,0是黄色,边框是36是因为,pygame矩形是以边为初始,向四周填充边框    pygame.draw.rect(playSurface,(255,255,0),Rect(0,0,270,270),36)    # 重置距离    board_reset(snake, snake_size, board)    # 如果蛇可以吃到食物,board_BFS返回true    # 并且board中除了蛇身(=SNAKE),其它的元素值表示从该点运动到食物的最短路径长    if board_BFS(food, snake, board):        best_move  = find_safe_way() # find_safe_way的唯一调用处    else:        best_move = follow_tail()    if best_move == ERR:        best_move = any_possible_move()    # 上面一次思考,只得出一个方向,运行一步    if best_move != ERR: make_move(best_move)    else:        print(score)#游戏结束后打印分数        break    # 控制游戏速度    fpsClock.tick(20)#20看上去速度正好
  • [技术干货] Python实现桶排序(基数排序)(转)
    基数排序基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或 bin sort。基数排序没有使用分治理念,放在本文一起讲解,是因为基数排序有一个对数字自身切分逻辑。基数排序的最基本思想:如对原始数列 nums = [3, 9, 8, 1, 6, 5, 7] 中的数字使用基数排序。先提供一个长度为 10 的新空数列(本文也称为排序数列)。为什么新空数列的长度要设置为 10?等排序完毕,相信大家就能找到答案。把原数列中的数字转存到新空数列中,转存方案:nums 中的数字 3 存储在新数列索引号为 3 的位置。nums 中的数字 9 存储在新数列索引号为 9 的位置。nums 中的数字 8 存储在新数列索引号为 8 的位置。……从上图可知,原数列中的数字所转存到排序数列中的位置,是数字所代表的索引号所指的位置。显然,经过转存后,新数列就是一个排好序的数列。新空数列的长度定义为多大由原始数列中数字的最大值来决定。编码实现:# 原数列nums = [3, 9, 8, 1, 6, 5, 7]# 找到数列中的最大值sort_nums=[0]*(max(nums)+1)for i in nums:    sort_nums[i]=iprint([i for i in sort_nums if i!=0])'''输出结果:[1,3,5,6,7,8,9]'''使用上述方案创建新空数据,如果数字之间的间隔较大时,新数列的空间浪费就非常大。如对 nums=[1,98,51,2,32,4,99,13,45] 使用上述方案排序,新空数列的长度要达到 99 ,真正需要保存的数字只有 7 个,如此空间浪费几乎是令人恐怖的。所以,有必要使用改良方案。如果在需要排序的数字中出现了 2 位以上的数字,则使用如下法则:先根据每一个数字个位上的数字进行存储。个位数是 1 存储在位置为 1 的位置,是 9 就存储在位置是 9 的位置。如下图:可看到有可能在同一个位置保存多个数字。这也是基数排序也称为桶排序的原因。一个位置就是一个桶,可以存放多个具有相同性质的数字。如上图:个位上数字相同的数字就在一个桶中。把存放在排序数列中的数字按顺序重新拿出来,这时的数列顺序变成 nums=[1,51,2,32,13,4,45,8,99]把重组后数列中的数字按十位上的数字重新存入排序数列。可以看到,经过 2 轮转存后,原数列就已经排好序。这个道理是很好理解的:现实生活中,我们在比较 2 个数字 大小时,可以先从个位上的数字相比较,然后再对十位上的数字比较。基数排序,很有生活的味道!!nums = [1, 98, 51, 2, 32, 4, 99, 13, 45]# 数列中的最大值m = max(nums)# 确定最大位数,用来确定需要转存多少次l = len(str(m))for i in range(l + 1):    # 排序数列,也是桶    sort_nums = [[] for _ in range(10)]    for n in nums:        # 分解数字个位上的数字        g_s = (n // 10 ** i) % 10        # 根据个位上的数字找到转存位置        sub_nums = sort_nums[g_s]        sub_nums.append(n)    # 合并数据    nums = []    for l in sort_nums:        nums.extend(l)print(nums)'''输出结果:[1, 2, 4, 13, 32, 45, 51, 98, 99]'''
  • [技术干货] Python实现归并排序
    归并排序归并排序算法也是基于分治思想。和希尔排序一样,需要对原始数列进行切分,但是切分的方案不一样。相比较希尔排序,归并排序的分解子问题,求解子问题,合并子问题的过程分界线非常清晰。可以说,归并排序更能完美诠释什么是分治思想。3.1 分解子问题归并排序算法的分解过程采用二分方案。把原始数列一分为二。然后在已经切分后的子数列上又进行二分。如此反复,直到子数列不能再分为止。如下图所示:如下代码,使用递归算法对原数列进行切分,通过输出结果观察切分过程:# 切分原数列def split_nums(nums):    print(nums)    if len(nums) > 1:        # 切分线,中间位置        sp_line = len(nums) // 2        split_nums(nums[0:sp_line])        split_nums(nums[sp_line:])nums = [3, 9, 8, 1, 6, 5, 7]split_nums(nums)求解子问题切分后,对每相邻 2 个子数列进行合并。当对相邻 2 个数列进行合并时,不是简单合并,需要保证合并后的数字是排序的。如下图所示:合并排序如何实现 2 个数字合并后数字有序?使用子数列中首数字比较算法进行合并排序。如下图演示了如何合并 nums01=[1,3,8,9]、nums02=[5,6,7] 2 个子数列。子数列必须是有序的!!数字 1 和 数字 5 比较,5 大于 1 ,数字 1 先位于合并数列中。数字 3 与数字 5 比较,数字 3 先进入合并数列中。数字 8 和数字 5 比较,数字 5 进入合并数列中。从头至尾,进行首数字大小比较,最后,可以保证合并后的数列是有序的。编写一个合并排序代码:如果仅仅是合并 2 个有序数列,本文提供 2 个方案:不增加额外的存储空间:把最终合并排序好的数字全部存储到其中的一个数列中。def merge_sort(nums01, nums02):    # 为 2 个数列创建 2 个指针    idx_01 = 0    idx_02 = 0    while idx_01 < len(nums01) and idx_02 < len(nums02):        if nums01[idx_01] > nums02[idx_02]:            # 这里不额外增加存储空间,如果数列 2 中的值大于数字 1 的插入到数列 1 中            nums01.insert(idx_01, nums02[idx_02])            idx_02 += 1        # 数列 1 的指针向右移动            idx_01 += 1    # 检查 nums02 中的数字是否已经全部合并到 nums01 中    while idx_02 < len(nums02):        nums01.append(nums02[idx_02])        idx_02 += 1nums01 = [1, 2, 8, 9]nums02 = [5, 6, 7, 12, 15]merge_sort(nums01, nums02)# 合并后的数字都存储到了第一个数列中print(nums01)'''输出结果:[1,2,5,6,7,8,9,12,15]'''增加一个空数列,用来保存最终合并的数字。# 使用附加数列nums=[]def merge_sort(nums01, nums02):    # 为 2 个数列创建 2 个指针    idx_01 = 0    idx_02 = 0    k=0    while idx_01 < len(nums01) and idx_02 < len(nums02):        if nums01[idx_01] > nums02[idx_02]:            nums.append(nums02[idx_02])            idx_02 += 1        else:            nums.append(nums01[idx_01])            idx_01 += 1        k+=1    # 检查是否全部合并    while idx_02 < len(nums02):        nums.append(nums02[idx_02])        idx_02 += 1    while idx_01 < len(nums01):        nums.append(nums01[idx_01])        idx_01 += 1nums01 = [1, 2, 8, 9]nums02 = [5, 6, 7, 12, 15]merge_sort(nums01, nums02)print(nums)前面是分步讲解切分和合并逻辑,现在把切分和合并逻辑合二为一,就完成了归并算法的实现:def merge_sort(nums):    if len(nums) > 1:        # 切分线,中间位置        sp_line = len(nums) // 2        nums01 = nums[:sp_line]        nums02 = nums[sp_line:]        merge_sort(nums01)        merge_sort(nums02)        # 为 2 个数列创建 2 个指针        idx_01 = 0        idx_02 = 0        k = 0        while idx_01 < len(nums01) and idx_02 < len(nums02):            if nums01[idx_01] > nums02[idx_02]:                # 合并后的数字要保存到原数列中                nums[k] = nums02[idx_02]                idx_02 += 1            else:                nums[k] = nums01[idx_01]                idx_01 += 1            k += 1        # 检查是否全部合并        while idx_02 < len(nums02):            nums[k] = nums02[idx_02]            idx_02 += 1            k += 1        while idx_01 < len(nums01):            nums[k] = nums01[idx_01]            idx_01 += 1            k += 1nums = [3, 9, 8, 1, 6, 5, 7]merge_sort(nums)print(nums)
  • [技术干货] Python实现希尔排序(转)
    希尔排序算法本质就是插入排序,或说是对插入排序的改良。其算法理念:让原始数列不断趋近于排序,从而降低插入排序的时间复杂度。希尔排序的实现流程:把原始数列从逻辑上切割成诸多个子数列。对每一个子数列使用插入排序算法排序。当所有子数列完成后,再对原数列进行最后一次插入算法排序。希尔排序算法的理念:当数列局部有序时,全局必然是趋向于有序”。希尔排序的关键在于如何切分子数列,切分方式可以有 2 种:任何时候使用分治理念解决问题时,分拆子问题都是关键的也是核心的。1 前后切分如有原始数列=[3,9,8,1,6,5,7] 采用前后分成 2 个子数列。前后分算得上是简单粗暴的切分方案,没有太多技术含量,这种一根筋的切分方式,对于原始问题的最终性能优化可能起不了太多影响。如上图所示,对子数列排序后,如果要实现原始数列中的所有数字从小到大排列有序,则后部分的数字差不多全部要移到时前部分数字的中间,其移动量是非常大的。后面的 4 个数字中,1 需要移动 3 次,5、6、7 需要移动 2 次, 肉眼可见的次数是 9 次。这种分法很难实现数字局部有序的正态分布,因为数字的位置变化不大。如下图是原始数列=[3,9,8,1,6,5,7] 的原始位置示意图:使用前后切分后的数字位置变化如下图所示,和上图相比较,数字的位置变化非常有限,而且是限定在一个很窄的范围内。也就是说子问题的求解结果对最终问题的结果的影响很微小。增量切分增量切分采用间隔切分方案,可能让数字局部有序以正态分布。增量切分,需要先设定一个增量值。如对原始数列=[3,9,8,1,6,5,7] 设置切分增量为 3 时,整个数列会被切分成 3 个逻辑子数列。增量数也决定最后能切分多少个子数列。对切分后的 3 个子数列排序后可得到下图:在此基础之上,再进行插入排序的的次数要少很多。使用增量切分后再排序,原始数列中的数字的位置变化范围较大。如数字 9 原始位置是 1,经过增量切分再排序后位置可以到 4。已经很接近 9 的最终位置 6 了。下图是增量切分后数字位置的变化图,可以看出来,几乎所有的数字都产生了位置变化 ,且位置变化的跨度较大。有整体趋于有序的势头。实现希尔排序算法时,最佳的方案是先初始化一个增量值,切分排序后再减少增量值,如此反复直到增量值等于 1 (也就是对原数列整体做插入排序)。增量值大,数字位置变化的跨度就大,增量值小,数字位置的变化会收紧。编码代码希尔排序:# 希尔排序def shell_sort(nums):    # 增量    increment = len(nums) // 2    # 新数列    while increment > 0:        # 增量值是多少,则切分的子数列就有多少        for start in range(increment):            insert_sort(nums, start, increment)        # 修改增量值,直到增量值为 1            increment = increment // 2        # 插入排序def insert_sort(nums, start, increment):    for back_idx in range(start + increment, len(nums), increment):        for front_idx in range(back_idx, 0, -increment):            if nums[front_idx] < nums[front_idx - increment]:                nums[front_idx], nums[front_idx - increment] = nums[front_idx - increment], nums[front_idx]            else:                breaknums = [3, 9, 8, 1, 6, 5, 7]shell_sort(nums)print(nums)
总条数:2474 到第 页
上滑加载中