Если вам нужно отслеживать использование вашей памяти во время выполнения, пакет java.lang.management предлагает MBeans, который может использоваться для мониторинга пулов памяти в вашей виртуальной машине (например, пространство с эденом, поколение и т. д.), а также сбор мусора поведение.
Свободное пространство кучи, указанное этими MBeans, будет сильно отличаться в зависимости от поведения GC, особенно если ваше приложение генерирует много объектов, которые позже будут GC-ed. Один из возможных подходов - отслеживать свободное пространство кучи после каждого полного GC, которое вы можете использовать, чтобы принять решение об освобождении памяти от сохраняющихся объектов.
В конечном счете, ваш лучший выбор - ограничить вы сохраняете память, насколько это возможно, пока производительность остается приемлемой. Как отмечалось в предыдущем комментарии, память всегда ограничена, но ваше приложение должно иметь стратегию борьбы с исчерпанием памяти.
Я написал это некоторое время назад, и он работает очень хорошо (отрицательные и все включены)
def code(number,base):
try:
int(number),int(base)
except ValueError:
raise ValueError('code(number,base): number and base must be in base10')
else:
number,base = int(number),int(base)
if base < 2:
base = 2
if base > 62:
base = 62
numbers = [0,1,2,3,4,5,6,7,8,9,"a","b","c","d","e","f","g","h","i","j",
"k","l","m","n","o","p","q","r","s","t","u","v","w","x","y",
"z","A","B","C","D","E","F","G","H","I","J","K","L","M","N",
"O","P","Q","R","S","T","U","V","W","X","Y","Z"]
final = ""
loc = 0
if number < 0:
final = "-"
number = abs(number)
while base**loc <= number:
loc = loc + 1
for x in range(loc-1,-1,-1):
for y in range(base-1,-1,-1):
if y*(base**x) <= number:
final = "{}{}".format(final,numbers[y])
number = number - y*(base**x)
break
return final
def decode(number,base):
try:
int(base)
except ValueError:
raise ValueError('decode(value,base): base must be in base10')
else:
base = int(base)
number = str(number)
if base < 2:
base = 2
if base > 62:
base = 62
numbers = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f",
"g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
"w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L",
"M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
final = 0
if number.startswith("-"):
neg = True
number = list(number)
del(number[0])
temp = number
number = ""
for x in temp:
number = "{}{}".format(number,x)
else:
neg = False
loc = len(number)-1
number = str(number)
for x in number:
if numbers.index(x) > base:
raise ValueError('{} is out of base{} range'.format(x,str(base)))
final = final+(numbers.index(x)*(base**loc))
loc = loc - 1
if neg:
return -final
else:
return final
извините за длину всего этого
Теперь для этого существует библиотека python.
Я работаю над созданием пакета pip для этого.
Я рекомендую использовать мои базы.py https : //github.com/kamijoutouma/bases.py , который был вдохновлен base.js
from bases import Bases
bases = Bases()
bases.toBase16(200) // => 'c8'
bases.toBase(200, 16) // => 'c8'
bases.toBase62(99999) // => 'q0T'
bases.toBase(200, 62) // => 'q0T'
bases.toAlphabet(300, 'aAbBcC') // => 'Abba'
bases.fromBase16('c8') // => 200
bases.fromBase('c8', 16) // => 200
bases.fromBase62('q0T') // => 99999
bases.fromBase('q0T', 62) // => 99999
bases.fromAlphabet('Abba', 'aAbBcC') // => 300
, относится к https://github.com/kamijoutouma/bases. py # known-basicalphabets , для каких базисных функций
Я как-то написал сценарий для этого, я думаю, это довольно элегантно:)
import string
BASE_LIST = string.digits + string.letters + '_@'
BASE_DICT = dict((c, i) for i, c in enumerate(BASE_LIST))
def base_decode(string, reverse_base=BASE_DICT):
length = len(reverse_base)
ret = 0
for i, c in enumerate(string[::-1]):
ret += (length ** i) * reverse_base[c]
return ret
def base_encode(integer, base=BASE_LIST):
if integer == 0:
return base[0]
length = len(base)
ret = ''
while integer != 0:
ret = base[integer % length] + ret
integer /= length
return ret
Пример использования:
for i in range(100):
print i, base_decode(base_encode(i)), base_encode(i)
reversed(string)
быстрее, чем нарезка string[::-1]
в функции base_decode.
– ENDOH takanao
25 January 2014 в 05:18
вы можете загрузить модуль zbase62 из pypi
, например
>>> import zbase62
>>> zbase62.b2a("abcd")
'1mZPsa'
Если вы используете фреймворк django, вы можете использовать модуль django.utils.baseconv.
>>> from django.utils import baseconv
>>> baseconv.base62.encode(1234567890)
1LY7VK
В дополнение к base62 baseconv также определил base2 / base16 / base36 / base56 / base64.
Следующий создатель декодера работает с любой разумной базой, имеет гораздо более аккуратный цикл и дает явное сообщение об ошибке, когда он встречает недопустимый символ.
def base_n_decoder(alphabet):
"""Return a decoder for a base-n encoded string
Argument:
- `alphabet`: The alphabet used for encoding
"""
base = len(alphabet)
char_value = dict(((c, v) for v, c in enumerate(alphabet)))
def f(string):
num = 0
try:
for char in string:
num = num * base + char_value[char]
except KeyError:
raise ValueError('Unexpected character %r' % char)
return num
return f
if __name__ == "__main__":
func = base_n_decoder('0123456789abcdef')
for test in ('0', 'f', '2020', 'ffff', 'abqdef'):
print test
print func(test)
**
в цикле.
– John Machin
15 January 2013 в 13:32
Извините, я не могу помочь вам с библиотекой здесь. Я предпочел бы использовать base64 и просто добавлять дополнительные символы к вашему выбору - если это возможно!
Тогда вы можете использовать модуль base64.
Если это действительно, действительно невозможно:
Вы можете сделать это самостоятельно (это псевдокод):
base62vals = []
myBase = 62
while num > 0:
reminder = num % myBase
num = num / myBase
base62vals.insert(0, reminder)
BASE_LIST = tuple("23456789ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_LIST))
BASE_LEN = len(BASE_LIST)
def nice_decode(str):
num = 0
for char in str[::-1]:
num = num * BASE_LEN + BASE_DICT[char]
return num
def nice_encode(num):
if not num:
return BASE_LIST[0]
encoding = ""
while num:
num, rem = divmod(num, BASE_LEN)
encoding += BASE_LIST[rem]
return encoding
Если вы ищете максимальную эффективность (например, django), вам нужно что-то вроде следующего. Этот код представляет собой комбинацию эффективных методов от Baishampayan Ghose и WoLpH и John Machin.
# Edit this list of characters as desired.
BASE_ALPH = tuple("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_ALPH))
BASE_LEN = len(BASE_ALPH)
def base_decode(string):
num = 0
for char in string:
num = num * BASE_LEN + BASE_DICT[char]
return num
def base_encode(num):
if not num:
return BASE_ALPH[0]
encoding = ""
while num:
num, rem = divmod(num, BASE_LEN)
encoding = BASE_ALPH[rem] + encoding
return encoding
Возможно, вы также захотите рассчитать свой словарь заранее. (Примечание: Кодирование со строкой показывает большую эффективность, чем со списком, даже с очень длинными номерами.)
>>> timeit.timeit("for i in xrange(1000000): base.base_decode(base.base_encode(i))", setup="import base", number=1)
2.3302059173583984
Закодировано и декодировано 1 миллион номеров менее чем за 2,5 секунды. (2,2 ГГц i7-2670QM)
tuple()
вокруг BASE_ALPH
. В Python каждая строка является итерируемой. Эта функция, конечно, используется enumerate()
. Так что код становится даже более скудным :)
– Luis Nell
18 April 2013 в 17:05
У меня есть библиотека Python для выполнения именно этого здесь: http://www.djangosnippets.org/snippets/1431/
Если вам нужно только создать короткий идентификатор (поскольку вы упомянете укороченные URL-адреса), а не кодировать / декодировать что-то, этот модуль может помочь:
Я получил большую пользу от других сообщений здесь. Мне сначала понадобился код python для проекта Django, но с тех пор я перешел на node.js, поэтому здесь представлена версия javascript кода (часть кодирования), которую предоставил Baishampayan Ghose.
var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
function base62_encode(n, alpha) {
var num = n || 0;
var alphabet = alpha || ALPHABET;
if (num == 0) return alphabet[0];
var arr = [];
var base = alphabet.length;
while(num) {
rem = num % base;
num = (num - rem)/base;
arr.push(alphabet.substring(rem,rem+1));
}
return arr.reverse().join('');
}
console.log(base62_encode(2390687438976, "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ"));
Лично мне нравится решение от Baishampayan, в основном из-за удаления запутанных символов.
Для полноты и решения с лучшей производительностью этот пост показывает способ использования Модуль base64 для Python.
Я надеюсь, что следующий фрагмент может помочь.
def num2sym(num, sym, join_symbol=''):
if num == 0:
return sym[0]
if num < 0 or type(num) not in (int, long):
raise ValueError('num must be positive integer')
l = len(sym) # target number base
r = []
div = num
while div != 0: # base conversion
div, mod = divmod(div, l)
r.append(sym[mod])
return join_symbol.join([x for x in reversed(r)])
Использование для вашего случая:
number = 367891
alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
print num2sym(number, alphabet) # will print '1xHJ'
Очевидно, вы можете указать другой алфавит, состоящий из меньшего или большего количества символов, затем он преобразует ваш номер в меньшая или большая база. Например, при предоставлении '01' в качестве алфавита выводится строка, представляющая входной номер как двоичный.
Вы можете сначала перетасовать алфавит, чтобы иметь уникальное представление чисел. Это может быть полезно, если вы используете службу сокращения URL-адресов.
if num < 0 or type(num) not in (int, long):
.
– martineau
25 June 2013 в 16:28
long
не существует в Py 3.x - поэтому вы можете использовать этот ответ .
– martineau
25 June 2013 в 19:25
isinstance(x, (type(1), type(2**32)))
.
– martineau
25 June 2013 в 20:35
Вот рекурсивный и итеративный способ сделать это. Итеративный немного быстрее в зависимости от количества выполнения.
def base62_encode_r(dec):
s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
return s[dec] if dec < 62 else base62_encode_r(dec / 62) + s[dec % 62]
print base62_encode_r(2347878234)
def base62_encode_i(dec):
s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
ret = ''
while dec > 0:
ret = s[dec % 62] + ret
dec /= 62
return ret
print base62_encode_i(2347878234)
def base62_decode_r(b62):
s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
if len(b62) == 1:
return s.index(b62)
x = base62_decode_r(b62[:-1]) * 62 + s.index(b62[-1:]) % 62
return x
print base62_decode_r("2yTsnM")
def base62_decode_i(b62):
s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
ret = 0
for i in xrange(len(b62)-1,-1,-1):
ret = ret + s.index(b62[i]) * (62**(len(b62)-i-1))
return ret
print base62_decode_i("2yTsnM")
if __name__ == '__main__':
import timeit
print(timeit.timeit(stmt="base62_encode_r(2347878234)", setup="from __main__ import base62_encode_r", number=100000))
print(timeit.timeit(stmt="base62_encode_i(2347878234)", setup="from __main__ import base62_encode_i", number=100000))
print(timeit.timeit(stmt="base62_decode_r('2yTsnM')", setup="from __main__ import base62_decode_r", number=100000))
print(timeit.timeit(stmt="base62_decode_i('2yTsnM')", setup="from __main__ import base62_decode_i", number=100000))
0.270266867033
0.260915645986
0.344734796766
0.311662500262
Вероятно, вы хотите base64, а не base62. Существует версия для совместимости с URL-адресами, поэтому дополнительные два символа-заполнителя не должны быть проблемой.
Процесс довольно прост; что base64 представляет 6 бит, а обычный байт представляет 8. Назначьте значение от 000000 до 111111 каждому из 64 выбранных символов и поместите 4 значения вместе, чтобы они соответствовали набору из 3 базовых 256 байтов. Повторите для каждого набора из 3 байтов, добавив в конец ваш выбор символа заполнения (обычно полезно 0).
$-_.+!*'(),;/?:@&=
Возможно, вы также можете использовать некоторые другие символы, например[]~
и т. Д. – Blixt 13 July 2009 в 15:32