これが最良の(すべての例はast
がインポートされると仮定し、私は、Python 2.7.1を使用していますことに注意してください)の例で説明することができる。なぜPythonはスライスステップにNoneを挿入しますか?
# Outputs: Slice(lower=Num(n=1), upper=Num(n=10), step=None)
ast.dump(ast.parse("l[1:10]").body[0].value.slice)
# Outputs: Slice(lower=Num(n=1), upper=Num(n=10), step=Name(id='None', ctx=Load()))
ast.dump(ast.parse("l[1:10:]").body[0].value.slice)
# Outputs: Slice(lower=Num(n=1), upper=None, step=None)
ast.dump(ast.parse("l[1:]").body[0].value.slice)
# Outputs: Slice(lower=None, upper=None, step=None)
ast.dump(ast.parse("l[:]").body[0].value.slice)
だから、私たちが見ることができるように、スライスASTノードでl[1:10]
結果lower
とupper
の両方が数値リテラルに設定され、空の第3子がstep
の子になります。しかし、[1:10:]
は、スライスのstep
子がNone
のリテラル式()になるように設定します。
さて、私は考えました。多分、Pythonは全く異なる種類の式としてl[1:10:]
とl[1:10]
を扱います。 Pythonの式参照(link)は確かにそうであるように思われました。 l[1:10]
は単純なスライスですが、l[1:10:]
は拡張スライス(1つのスライスアイテムのみ)です。
しかし、拡張スライスのコンテキストでも、step引数は特別に扱われます。私たちは、上または1つのスライス項目に拡張スライスで下限を無視しようとすると、私たちは、空の子供で終わる:
# Outputs: Slice(lower=Num(n=1), upper=None, step=Name(id='None', ctx=Load()))
ast.dump(ast.parse("l[1::]").body[0].value.slice)
# Outputs: Slice(lower=None, upper=Num(n=10), step=Name(id='None', ctx=Load()))
ast.dump(ast.parse("l[:10:]").body[0].value.slice)
また、さらに検査時にASTも拡張スライシングとしてこれらのスライシングを扱うことはありません。ここでスライシングが実際のように見える拡張するものです。だからここ
# Outputs: ExtSlice(dims=[Slice(lower=None, upper=None, step=Name(id='None', ctx=Load())), Slice(lower=None, upper=None, step=Name(id='None', ctx=Load()))])
ast.dump(ast.parse("l[::, ::]").body[0].value.slice)
は私の結論です:ASTは常に何らかの理由で特別なstep
パラメータを扱い、、unrelatedly、Slice
ASTノードは、(私はそこにドンを推測長いスライスを表し、私はそれが望ましいだろうと思うが)Slice
クラスShortSlice
とLongSlice
である必要があります。したがって、単一アイテムの拡張スライスは通常のSlice
ノードとして表現でき、なんらかの理由で実行されます。 None
のパラメータをデフォルトとして解釈させることは間違っているようですが、それは意図的な設計上の決定だったことを理解しています。 None
リテラル挿入と長いスライスをSlice
ノードとして扱うことは、事故(または古いデザインのアーティファクト)のように見えるだけです。
もっと詳しい情報が他にありますか?拡張スライス表記で、このような処置がなければ