ひるあんどんブログ

色々なことに手を出してみるブログ

Number Base

数学の授業の基数(radix)と 記数法(Numeral system)を覚えていますか? それを使って練習してみましょう。 (訳注: 基数は例えば10進数の10のことです。底と呼ばれることもあります。記数法はN進法のことです。この場合Nが基数になります。 詳しくは位取り記数法を参照してください)

あなたには文字列で表現された正の数とその基数が一緒に与えられます。 あなたの関数はこれを10進数に変換しなければいけません。 基数は37より小さく1より大きいです。 このタスクは文字列に数字と文字A-Zを使います。

数が変換できない場合に気をつけてください。 例えば: "1A"は基数9(訳注: 9進数)に変換できません。 このような場合にあなたの関数は-1を返さなければいけません。

ヒント(Tips): あなたはこのタスクを以下を使って簡単に解くことができます。 int()変換と 例外(exception)の処理 (ValueErrorを見ましょう)。

入力: 二つの引数。数の文字列と基数の整数。

出力: 変換された数、整数。

例:

checkio("AF", 16) == 175

checkio("101", 2) == 5

checkio("101", 5) == 26

checkio("Z", 36) == 35

checkio("AB", 10) == -1
どのように使われるか: ここであなたは様々な記数法を使う方法と例外の処理を学ぶでしょう。

事前条件:
re.match("\A[A-Z0-9]\Z", str_number)
0 < len(str_number) ≤ 10
2 ≤ radix ≤ 36

def checkio(str_number, radix):
    try:
        return int(str_number,radix)
    except:
        return -1

#These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':
    assert checkio("AF", 16) == 175, "Hex"
    assert checkio("101", 2) == 5, "Bin"
    assert checkio("101", 5) == 26, "5 base"
    assert checkio("Z", 36) == 35, "Z base"
    assert checkio("AB", 10) == -1, "B > A > 10"
class int(x=0)
class int(x, base=10)

    数値または文字列 x から生成された整数を返します。引数が与えられない場合には 0 を返します。 x が数値である場合は x.__int__() を返します。浮動小数点数については、これは 0 の方へ切り詰めます。

    x が数値でない場合、あるいは base が与えられた場合、 x は基数 base の integer literal で表された文字列、 bytes あるいは bytearray のインスタンスでなければなりません。オプションで、リテラルの前に + あるいは - を (中間のスペースなしで) 付けることができます。また、リテラルは余白で囲むことができます。基数 n のリテラルは 0 から n-1 の数字で構成され、値 10-35 を持つ a から z (または A から Z) を含みます。デフォルトの base は 10 です。許される値は 0 と 2-36 です。基数 2, 8, 16 のリテラルは、オプションでコード中の整数リテラルのように 0b/0B, 0o/0O, or 0x/0X を前に付けることができます。基数 0 はコードリテラルとして正確に解釈することを意味します。その結果、実際の基数は 2, 8, 10, 16 のどれかです。したがって int('010', 0) は有効ではありませんが、 int('010') や int('010', 8) は有効です。

ヒントにもある通り、intを使って変換して、もじ例外が発生したら-1を投げる。おわり

checkioやると、どんどん関数おぼえていくので楽しいです。

clear 1位


def checkio(*a):

    try: return int(*a)

    except ValueError: return -1

例外はちゃんと、なんの例外を投げるかを指定したほうが行儀が良いようだ。たしかに、自分のコードでは全ての例外を同じように処理してしまう。

引数の*aは、任意引数リストというらしい。チュートリアルでは、使うことは少ないとされている。

4.7.3. 任意引数リスト

最後に、最も使うことの少ない選択肢として、関数が任意の個数の引数で呼び出せるよう指定する方法があります。これらの引数はタプル (タプルとシーケンス を参照) に格納されます。可変個の引数の前に、ゼロ個かそれ以上の引数があっても構いません。

def write_multiple_items(file, separator, *args):
    file.write(separator.join(args))

通常このような 可変 パラメタは、関数に渡される入力引数の残りを全て掬い取るために、仮引数リストの最後に置かれます。*args パラメタの後にある仮引数は ‘キーワード専用’ 引数で、位置指定引数ではなくキーワード引数としてのみ使えます。

>>> def concat(*args, sep="/"):
...    return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'

タプルに保存された引数を、アンパックして渡しているんだなぁ。

4.7.4. 引数リストのアンパック

引数がすでにリストやタプルになっていて、個別な固定引数を要求する関数呼び出しに渡すためにアンパックする必要がある場合には、逆の状況が起こります。例えば、組み込み関数 range() は引数 start と stop を別に与える必要があります。個別に引数を与えることができない場合、関数呼び出しを * 演算子を使って書き、リストやタプルから引数をアンパックします:

>>> list(range(3, 6))            # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args))            # call with arguments unpacked from a list
[3, 4, 5]

同じやりかたで、** オペレータを使って辞書でもキーワード引数を渡すことができます:

>>> def parrot(voltage, state='a stiff', action='voom'):
...     print("-- This parrot wouldn't", action, end=' ')
...     print("if you put", voltage, "volts through it.", end=' ')
...     print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
    • This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !