python标识符可以以数字开头吗_如何将Python标识符转换为数字?

In the question referenced above, a solution was found for turning a numbe into a name. This question asks just the opposite. How can you convert a name back into a number? So far, this is what I have:

>>> import string

>>> HEAD_CHAR = ''.join(sorted(string.ascii_letters + '_'))

>>> TAIL_CHAR = ''.join(sorted(string.digits + HEAD_CHAR))

>>> HEAD_BASE, TAIL_BASE = len(HEAD_CHAR), len(TAIL_CHAR)

>>> def number_to_name(number):

"Convert a number into a valid identifier."

if number < HEAD_BASE:

return HEAD_CHAR[number]

q, r = divmod(number - HEAD_BASE, TAIL_BASE)

return number_to_name(q) + TAIL_CHAR[r]

>>> [number_to_name(n) for n in range(117)]

['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', 'A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ', 'A_', 'Aa', 'Ab', 'Ac', 'Ad', 'Ae', 'Af', 'Ag', 'Ah', 'Ai', 'Aj', 'Ak', 'Al', 'Am', 'An', 'Ao', 'Ap', 'Aq', 'Ar', 'As', 'At', 'Au', 'Av', 'Aw', 'Ax', 'Ay', 'Az', 'B0']

>>> def name_to_number(name):

assert name, 'Name must exist!'

head, *tail = name

number = HEAD_CHAR.index(head)

for position, char in enumerate(tail):

if position:

number *= TAIL_BASE

else:

number += HEAD_BASE

number += TAIL_CHAR.index(char)

return number

>>> [name_to_number(number_to_name(n)) for n in range(117)]

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 54]

The function number_to_name works perfectly, and name_to_number works up until it gets to number 116. At that point, the function returns 54 instead. Does anyone see the code's problem?

Solution based on recursive's answer:

import string

HEAD_CHAR = ''.join(sorted(string.ascii_letters + '_'))

TAIL_CHAR = ''.join(sorted(string.digits + HEAD_CHAR))

HEAD_BASE, TAIL_BASE = len(HEAD_CHAR), len(TAIL_CHAR)

def name_to_number(name):

if not name.isidentifier():

raise ValueError('Name must be a Python identifier!')

head, *tail = name

number = HEAD_CHAR.index(head)

for char in tail:

number *= TAIL_BASE

number += TAIL_CHAR.index(char)

return number + sum(HEAD_BASE * TAIL_BASE ** p for p in range(len(tail)))

解决方案

Unfortunately, these identifiers don't yield to traditional constant base encoding techniques. For example "A" acts like a zero, but leading "A"s change the value. In normal number systems leading zeroes do not. There could be multiple approaches, but I settled on one that calculates the total number of identifiers with fewer digits, and starts from that.

def name_to_number(name):

assert name, 'Name must exist!'

skipped = sum(HEAD_BASE * TAIL_BASE ** i for i in range(len(name) - 1))

val = reduce(

lambda a,b: a * TAIL_BASE + TAIL_CHAR.index(b),

name[1:],

HEAD_CHAR.index(name[0]))

return val + skipped

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值