Last active
January 14, 2024 18:16
-
-
Save toddlerya/e134007fada31377659a9281e21767fc to your computer and use it in GitHub Desktop.
62进制与10进制转换,主要用于短URL生成解析
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# encoding: utf-8 | |
# author: toddlerya | |
# date: 2019/03/31 | |
# python_version: 3.7.1 | |
import string | |
import unittest | |
class Base62(object): | |
""" | |
基于abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789共计62个ascii字符 | |
构建62进制编码, 实现正整型十进制数据字符编码和解码 | |
""" | |
def __init__(self): | |
self.BASE_STR = string.ascii_letters + string.digits | |
self.BASE = len(self.BASE_STR) | |
def __10to62(self, digit, value=None): | |
# 小心value参数的默认传参数陷阱 | |
# 不应写为value=[], 这将导致只有一次初始化, 每次调用列表的值都会累加 | |
# 应该声明为None, 只有为None才进行初始化, 这样能保持每次调用都会初始化此参数 | |
# https://pythonguidecn.readthedocs.io/zh/latest/writing/gotchas.html | |
if value is None: | |
value = list() | |
rem = int(digit % self.BASE) | |
value.append(self.BASE_STR[rem]) | |
div = int(digit / self.BASE) | |
if div > 0: | |
value = self.__10to62(div, value) | |
return value | |
def __62to10(self, str_value): | |
value_list = list(str_value) | |
value_list.reverse() | |
temp_list = [self.BASE_STR.index(ele) * (self.BASE ** n) for n, ele in enumerate(value_list)] | |
return sum(temp_list) | |
def encode_10to62(self, digit: int) -> str: | |
""" | |
10进制转为62进制 | |
""" | |
if not isinstance(digit, int) or digit < 0: | |
raise TypeError('请输入正整数') | |
value = self.__10to62(digit) | |
value.reverse() | |
value = ''.join(value) | |
return value | |
def decode_62to10(self, str62: str) -> int: | |
""" | |
62进制转为10进制 | |
""" | |
check = sum([1 for ele in str62 if ele not in self.BASE_STR]) | |
if check > 0 or len(str62) == 0 or not isinstance(str62, str): | |
raise TypeError('请输入正确的62进制数') | |
return self.__62to10(str62) | |
class TestBase62(unittest.TestCase): | |
def setUp(self): | |
self.code = Base62() | |
def test_encode_10to62_border(self): | |
self.assertEqual(first=self.code.encode_10to62(0), second='a') | |
self.assertEqual(first=self.code.encode_10to62(1), second='b') | |
self.assertEqual(first=self.code.encode_10to62(61), second='9') | |
self.assertEqual(first=self.code.encode_10to62(62), second='ba') | |
def test_encode_10to62_nornal(self): | |
self.assertEqual(first=self.code.encode_10to62(122262), second='FX8') | |
def test_decode_62to10_border(self): | |
self.assertEqual(first=self.code.decode_62to10('a'), second=0) | |
self.assertEqual(first=self.code.decode_62to10('b'), second=1) | |
self.assertEqual(first=self.code.decode_62to10('9'), second=61) | |
self.assertEqual(first=self.code.decode_62to10('ba'), second=62) | |
def test_decode_62to10_nornal(self): | |
self.assertEqual(first=self.code.decode_62to10('FX8'), second=122262) | |
def test_encode_10to62_datatype_error(self): | |
self.assertRaises(TypeError, self.code.encode_10to62, -1) | |
self.assertRaises(TypeError, self.code.encode_10to62, -1212) | |
self.assertRaises(TypeError, self.code.encode_10to62, 22.1212) | |
self.assertRaises(TypeError, self.code.encode_10to62, '') | |
self.assertRaises(TypeError, self.code.encode_10to62, 'safs#121') | |
def test_decode_62to10_datatype_error(self): | |
self.assertRaises(TypeError, self.code.decode_62to10, -1) | |
self.assertRaises(TypeError, self.code.decode_62to10, -1212) | |
self.assertRaises(TypeError, self.code.decode_62to10, 22.1212) | |
self.assertRaises(TypeError, self.code.decode_62to10, '') | |
self.assertRaises(TypeError, self.code.decode_62to10, 'safs#121') | |
if __name__ == "__main__": | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
a="aa"
b=Base32()
a==b.encode_10to62(b.decode_62to10(a))