私たちは夢中になる前に、次のいずれかがあなたのパフォーマンス要件を満たすかどうかを確認:
mylist.reverse(); json.dumps(mylist); mylist.reverse()
json.dumps(mylist[::-1])
json.dumps(tuple(reversed(mylist)))
あなたは(*一番下に例)を行うことは非常に簡単です、あなた自身のJSONEncoderのデフォルトの関数を定義言及
None, True, False, str, int, float, list, tuple, dict
ラージオブジェクトを作成し、リストやタプルにイテレータを変換する、:json.JSONEncoderは、次のいずれかにオブジェクトを変換するには、デフォルトの機能を必要とするので、私はそれがここで働くとは思いませんこれは私たちが避けようとしているものです。
jsonライブラリを変更するか、monkey-patchする必要があります。
ここにCPythonのソースコードjson.encoderがあります。 PyPy、Jython、その他のPythonの実装はおそらくjsonモジュールに同じコードを使用しています。パフォーマンス上の理由から
https://github.com/python/cpython/blob/master/Lib/json/encoder.py#L204
def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
_key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
## HACK: hand-optimized bytecode; turn globals into locals
ValueError=ValueError,
dict=dict,
float=float,
id=id,
int=int,
isinstance=isinstance,
list=list,
str=str,
tuple=tuple,
_intstr=int.__str__,
...
def _iterencode(o, _current_indent_level):
if isinstance(o, str):
yield _encoder(o)
...
elif isinstance(o, (list, tuple)):
yield from _iterencode_list(o, _current_indent_level)
# Add support for processing iterators
elif isinstance(o, iterator_types):
# Side-effect: this will consume the iterator.
# This is probably why it's not included in the official json module
# We could use itertools.tee to be able to iterate over
# the original iterator while still having an unconsumed iterator
# but this would require updating all references to the original
# iterator with the new unconsumed iterator.
# The side effect may be unavoidable.
yield from _iterencode_list(o, _current_index_level)
は、関数の外にイテレータ型を定義し、ローカルとしてそれを持って帰りたいと思うでしょう。
str_iterator = type(iter(str() ))
list_iterator = type(iter(list() ))
tuple_iterator = type(iter(tuple() ))
range_iterator = type(iter(range(0)))
list_reverseiterator = type(reversed(list() ))
reverseiterator = type(reversed(tuple())) #same as <class 'reversed'>
# Add any other iterator classes that you need here, plus any container data types that json doesn't support (sets, frozensets, bytes, bytearray, array.array, numpy.array)
iterator_types = (str_iterator, list_iterator, tuple_iterator, range_iterator,
list_reverseiterator, reversed)
猿パッチルートに移動する場合は、json.encoderを再定義する必要があります。_make_iterencode機能、これらの変更は、このような何かを見isinstance(X, (list, tuple)+iterator_types)
import json
def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
_key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
iterable_types=_get_iterable_types(),
...
):
...
json.encoder._make_iterencode = _make_iterencode
でisinstance(X, (list, tuple))
の出現をすべて置き換える:約束どおりコピーせずにイテレータをダンプするために有用ではないものの、独自のデフォルトの関数を定義する方法、https://github.com/python/cpython/pull/3034/files
*をイテレータをリストまたはタプルに挿入します。
また
class JSONEncoderThatSupportsIterators(json.JSONEncoder):
def default(self, o):
try:
iterable = iter(o)
except TypeError:
pass
else:
return list(iterable)
# Let the base class default method raise the TypeError
return json.JSONEncoder.default(self, o)
li = range(10000000) # or xrange if Python 2
dumped = JSONEncoderThatSupportsIterators().encode(reversed(li))
assert dumped.startswith('[999999, 999998, 999997, ')
assert dumped.endswith('6, 5, 4, 3, 2, 1, 0]')
、というよりもjson.JSONEncoder
をサブクラス化するには、default(self, o)
関数を定義し、json.dumps(default=default)
への引数として渡すことができます。
'mylist.reverse()'を使ってリストを逆順にします(コピーを避けます)。 - あなたのシリアライゼーションを行います。 –
新しいリストを作成するよりも優れていますが、それでもまだ必要のない中間ステップが作成されます。しかし、ヒントのおかげで。 :) – silentnights
jsonライブラリを見ていて、それは見た目ほど単純ではありません。 JSONDecoder.defaultには、*例えば、任意のイテレータをサポートするために、* ...でも可能ですが、それは、その部分集合に意味のあるiterableからリストを返すことを示唆しています(例えば、 '{test:range (10)} '展開されましたが、あなたのデータの' reverse '全体ではありません。いくつかのレベルは、C実装やその他のビットで '_functions'を入れ子にした' _functions'で処理するという点でさらに複雑です。私は 'list.reverse'をしっかりとしています:) –