热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python版本号排序_在Python中对版本排序

主要编辑:旧答案太不通俗。这里有两个更漂亮的解决方案。所以,我现在看到了三种实现预定的方法,在实际发布之前发布候选“rc”。我以前的命令式

主要编辑:旧答案太不通俗。这里有两个更漂亮的解决方案。

所以,我现在看到了三种实现预定的方法,在实际发布之前发布候选“rc”。我以前的命令式排序

使用“b”而不是“rc”,以便使用来自同一个包的StrictVersion

扩展Version类以添加对任意标记和标记排序的支持

一。旧式命令式排序from distutils.version import LooseVersion

versions = ["1.7.0", "1.7.0.rc0", "1.8.0"]

lv = [LooseVersion(v) for v in versions]

lv.sort()

sorted_rc = [v.vstring for v in lv]

import re

p = re.compile('rc\\d+$')

i = 0

# skip the first RCs

while i + 1

m = p.search(sorted_rc[i])

if m:

i += 1

else:

break

while i + 1

tmp = sorted_rc[i]

m = p.search(sorted_rc[i+1])

if m and sorted_rc[i+1].startswith(tmp):

sorted_rc[i] = sorted_rc[i+1]

sorted_rc[i+1] = tmp

i += 1

有了这个我得到:['1.7.0rc0', '1.7.0', '1.11.0']

2。用“b”代替“rc”

如果允许您的1.7.0.rc0以1.7.0a0或1.7.0b0的形式写入,包distutils.version也有另一个类StrictVersion来执行任务,该类记录alpha或beta版本。

即:from distutils.version import StrictVersion

versions = ["1.7.0", "1.7.0b0", "1.11.0"]

sorted(versions, key=StrictVersion)

这就提供了:['1.7.0b0', '1.7.0', '1.11.0']

可以使用re模块完成从一个表单到另一个表单的转换。

三。扩展版本类

先前解决方案的明显问题是StrictVersion缺乏灵活性。更改version_re类属性以使用rc而不是a或b,即使它接受1.7.1rc0,仍然将其打印为1.7.1r0(从python 2.7.3开始)。

我们可以通过实现自己的自定义版本类来实现它。可以这样做,通过一些单元测试来确保正确性,至少在某些情况下:#!/usr/bin/python

# file: version2.py

from distutils import version

import re

import functools

@functools.total_ordering

class NumberedVersion(version.Version):

"""

A more flexible implementation of distutils.version.StrictVersion

This implementation allows to specify:

- an arbitrary number of version numbers:

not only '1.2.3' , but also '1.2.3.4.5'

- the separator between version numbers:

'1-2-3' is allowed when '-' is specified as separator

- an arbitrary ordering of pre-release tags:

1.1alpha3 <1.1beta2 <1.1rc1 <1.1

when ["alpha", "beta", "rc"] is specified as pre-release tag list

"""

def __init__(self, vstring&#61;None, sep&#61;&#39;.&#39;, prerel_tags&#61;(&#39;a&#39;, &#39;b&#39;)):

version.Version.__init__(self)

# super() is better here, but Version is an old-style class

self.sep &#61; sep

self.prerel_tags &#61; dict(zip(prerel_tags, xrange(len(prerel_tags))))

self.version_re &#61; self._compile_pattern(sep, self.prerel_tags.keys())

self.sep_re &#61; re.compile(re.escape(sep))

if vstring:

self.parse(vstring)

_re_prerel_tag &#61; &#39;rel_tag&#39;

_re_prerel_num &#61; &#39;tag_num&#39;

def _compile_pattern(self, sep, prerel_tags):

sep &#61; re.escape(sep)

tags &#61; &#39;|&#39;.join(re.escape(tag) for tag in prerel_tags)

if tags:

release_re &#61; &#39;(?:(?P{tags})(?P\d&#43;))?&#39;\

.format(tags&#61;tags, tn&#61;self._re_prerel_tag, nn&#61;self._re_prerel_num)

else:

release_re &#61; &#39;&#39;

return re.compile(r&#39;^(\d&#43;)(?:{sep}(\d&#43;))*{rel}$&#39;\

.format(sep&#61;sep, rel&#61;release_re))

def parse(self, vstring):

m &#61; self.version_re.match(vstring)

if not m:

raise ValueError("invalid version number &#39;{}&#39;".format(vstring))

tag &#61; m.group(self._re_prerel_tag)

tag_num &#61; m.group(self._re_prerel_num)

if tag is not None and tag_num is not None:

self.prerelease &#61; (tag, int(tag_num))

vnum_string &#61; vstring[:-(len(tag) &#43; len(tag_num))]

else:

self.prerelease &#61; None

vnum_string &#61; vstring

self.version &#61; tuple(map(int, self.sep_re.split(vnum_string)))

def __repr__(self):

return "{cls} (&#39;{vstring}&#39;, &#39;{sep}&#39;, {prerel_tags})"\

.format(cls&#61;self.__class__.__name__, vstring&#61;str(self),

sep&#61;self.sep, prerel_tags &#61; list(self.prerel_tags.keys()))

def __str__(self):

s &#61; self.sep.join(map(str,self.version))

if self.prerelease:

return s &#43; "{}{}".format(*self.prerelease)

else:

return s

def __lt__(self, other):

"""

Fails when the separator is not the same or when the pre-release tags

are not the same or do not respect the same order.

"""

# TODO deal with trailing zeroes: e.g. "1.2.0" &#61;&#61; "1.2"

if self.prerel_tags !&#61; other.prerel_tags or self.sep !&#61; other.sep:

raise ValueError("Unable to compare: instances have different"

" structures")

if self.version &#61;&#61; other.version and self.prerelease is not None and\

other.prerelease is not None:

tag_index &#61; self.prerel_tags[self.prerelease[0]]

other_index &#61; self.prerel_tags[other.prerelease[0]]

if tag_index &#61;&#61; other_index:

return self.prerelease[1]

return tag_index

elif self.version &#61;&#61; other.version:

return self.prerelease is not None and other.prerelease is None

return self.version

def __eq__(self, other):

tag_index &#61; self.prerel_tags[self.prerelease[0]]

other_index &#61; other.prerel_tags[other.prerelease[0]]

return self.prerel_tags &#61;&#61; other.prerel_tags and self.sep &#61;&#61; other.sep\

and self.version &#61;&#61; other.version and tag_index &#61;&#61; other_index and\

self.prerelease[1] &#61;&#61; other.prerelease[1]

import unittest

class TestNumberedVersion(unittest.TestCase):

def setUp(self):

self.v &#61; NumberedVersion()

def test_compile_pattern(self):

p &#61; self.v._compile_pattern(&#39;.&#39;, [&#39;a&#39;, &#39;b&#39;])

tests &#61; {&#39;1.2.3&#39;: True, &#39;1a0&#39;: True, &#39;1&#39;: True, &#39;1.2.3.4a5&#39;: True,

&#39;b&#39;: False, &#39;1c0&#39;: False, &#39; 1&#39;: False, &#39;&#39;: False}

for test, result in tests.iteritems():

self.assertEqual(result, p.match(test) is not None, \

"test: {} result: {}".format(test, result))

def test_parse(self):

tests &#61; {"1.2.3.4a5": ((1, 2, 3, 4), (&#39;a&#39;, 5))}

for test, result in tests.iteritems():

self.v.parse(test)

self.assertEqual(result, (self.v.version, self.v.prerelease))

def test_str(self):

tests &#61; ((&#39;1.2.3&#39;,), (&#39;10-2-42rc12&#39;, &#39;-&#39;, [&#39;rc&#39;]))

for t in tests:

self.assertEqual(t[0], str(NumberedVersion(*t)))

def test_repr(self):

v &#61; NumberedVersion(&#39;1,2,3rc4&#39;, &#39;,&#39;, [&#39;lol&#39;, &#39;rc&#39;])

expected &#61; "NumberedVersion (&#39;1,2,3rc4&#39;, &#39;,&#39;, [&#39;lol&#39;, &#39;rc&#39;])"

self.assertEqual(expected, repr(v))

def test_order(self):

test &#61; ["1.7.0", "1.7.0rc0", "1.11.0"]

expected &#61; [&#39;1.7.0rc0&#39;, &#39;1.7.0&#39;, &#39;1.11.0&#39;]

versions &#61; [NumberedVersion(v, &#39;.&#39;, [&#39;rc&#39;]) for v in test]

self.assertEqual(expected, list(map(str,sorted(versions))))

if __name__ &#61;&#61; &#39;__main__&#39;:

unittest.main()

所以&#xff0c;可以这样使用&#xff1a;import version2

versions &#61; ["1.7.0", "1.7.0rc2", "1.7.0rc1", "1.7.1", "1.11.0"]

sorted(versions, key&#61;lambda v: version2.NumberedVersion(v, &#39;.&#39;, [&#39;rc&#39;]))

输出&#xff1a;[&#39;1.7.0rc1&#39;, &#39;1.7.0rc2&#39;, &#39;1.7.0&#39;, &#39;1.7.1&#39;, &#39;1.11.0&#39;]

因此&#xff0c;总之&#xff0c;使用python自带的电池或推出自己的电池。

关于这个实现&#xff1a;可以通过处理发行版中的尾随零来改进它&#xff0c;并记住正则表达式的编译。



推荐阅读
  • 探讨 jBPM 数据库表结构设计的精要与实践
    探讨 jBPM 数据库表结构设计的精要与实践 ... [详细]
  • 在Java编程中,为了提高代码的可读性和执行效率,建议优先使用局部变量来存储方法的返回值,而不是多次调用同一个方法。这样不仅可以减少方法调用的开销,还能避免潜在的性能问题。此外,使用局部变量还可以增强代码的可维护性和调试便利性。 ... [详细]
  • 如何使用 net.sf.extjwnl.data.Word 类及其代码示例详解 ... [详细]
  • 从零起步:使用IntelliJ IDEA搭建Spring Boot应用的详细指南
    从零起步:使用IntelliJ IDEA搭建Spring Boot应用的详细指南 ... [详细]
  • 在CentOS上部署和配置FreeSWITCH
    在CentOS系统上部署和配置FreeSWITCH的过程涉及多个步骤。本文详细介绍了从源代码安装FreeSWITCH的方法,包括必要的依赖项安装、编译和配置过程。此外,还提供了常见的配置选项和故障排除技巧,帮助用户顺利完成部署并确保系统的稳定运行。 ... [详细]
  • 本文作为“实现简易版Spring系列”的第五篇,继前文深入探讨了Spring框架的核心技术之一——控制反转(IoC)之后,将重点转向另一个关键技术——面向切面编程(AOP)。对于使用Spring框架进行开发的开发者来说,AOP是一个不可或缺的概念。了解AOP的背景及其基本原理,对于掌握这一技术至关重要。本文将通过具体示例,详细解析AOP的实现机制,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文深入探讨了 MXOTDLL.dll 在 C# 环境中的应用与优化策略。针对近期公司从某生物技术供应商采购的指纹识别设备,该设备提供的 DLL 文件是用 C 语言编写的。为了更好地集成到现有的 C# 系统中,我们对原生的 C 语言 DLL 进行了封装,并利用 C# 的互操作性功能实现了高效调用。此外,文章还详细分析了在实际应用中可能遇到的性能瓶颈,并提出了一系列优化措施,以确保系统的稳定性和高效运行。 ... [详细]
  • 在 Android 开发中,通过合理利用系统通知服务,可以显著提升应用的用户交互体验。针对 Android 8.0 及以上版本,开发者需首先创建并注册通知渠道。本文将详细介绍如何在应用中实现这一功能,包括初始化通知管理器、创建通知渠道以及发送通知的具体步骤,帮助开发者更好地理解和应用这些技术细节。 ... [详细]
  • MongoDB Aggregates.group() 方法详解与编程实例 ... [详细]
  • 深入解析零拷贝技术(Zerocopy)及其应用优势
    零拷贝技术(Zero-copy)是Netty框架中的一个关键特性,其核心在于减少数据在操作系统内核与用户空间之间的传输次数。通过避免不必要的内存复制操作,零拷贝显著提高了数据传输的效率和性能。本文将深入探讨零拷贝的工作原理及其在实际应用中的优势,包括降低CPU负载、减少内存带宽消耗以及提高系统吞吐量等方面。 ... [详细]
  • 深入解析 Android Drawable:第六阶段进阶指南 ... [详细]
  • 本文提供了 RabbitMQ 3.7 的快速上手指南,详细介绍了环境搭建、生产者和消费者的配置与使用。通过官方教程的指引,读者可以轻松完成初步测试和实践,快速掌握 RabbitMQ 的核心功能和基本操作。 ... [详细]
  • Android ListView 自定义 CheckBox 实现列表项多选功能详解
    本文详细介绍了在Android开发中如何在ListView的每一行添加CheckBox,以实现列表项的多选功能。用户不仅可以通过点击复选框来选择项目,还可以通过点击列表的任意一行来完成选中操作,提升了用户体验和操作便捷性。同时,文章还探讨了相关的事件处理机制和布局优化技巧,帮助开发者更好地实现这一功能。 ... [详细]
  • 表面缺陷检测数据集综述及GitHub开源项目推荐
    本文综述了表面缺陷检测领域的数据集,并推荐了多个GitHub上的开源项目。通过对现有文献和数据集的系统整理,为研究人员提供了全面的资源参考,有助于推动该领域的发展和技术进步。 ... [详细]
  • 如何在Android应用中设计和实现专业的启动欢迎界面(Splash Screen)
    在Android应用开发中,设计与实现一个专业的启动欢迎界面(Splash Screen)至关重要。尽管Android设计指南对使用Splash Screen的态度存在争议,但一个精心设计的启动界面不仅能提升用户体验,还能增强品牌识别度。本文将探讨如何在遵循最佳实践的同时,通过技术手段实现既美观又高效的启动欢迎界面,包括加载动画、过渡效果以及性能优化等方面。 ... [详细]
author-avatar
666666顺2502878433
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有