Pythonのジェネレータとは、yield を使って値を1つずつ作りながら返す関数(またはその戻り値のオブジェクト)です。 すべての値をリストに入れてから返すのではなく、「必要になった分だけその場で作る」ため、大量のデータでもメモリをほとんど使わずに処理できます。

この記事では、まずイテレータ・ジェネレータ関数・ジェネレータ式の関係を早見表で整理します。次に、リストとのメモリ差を sys.getsizeof と tracemalloc で実測し、200万行(87MB)のログファイルを1行ずつ処理するパイプラインを組みます。さらに itertools との組み合わせ、yield from、send・throw・close、return の値の受け取り方、つまずきやすい点をすべて実行結果つきで解説し、非同期ジェネレータと contextlib.contextmanager との関係まで紹介します。

検証環境:Linux、Python 3.14.7(比較用に Python 3.11.15)。

ジェネレータの早見表

用語 正体 作り方 何度も回せるか
イテラブル for で回せるもの list、dict、str、ファイル、__iter__ を持つクラス ○(リスト等)
イテレータ next() で次の値を返すもの iter(イテラブル) ×(1回きり)
ジェネレータ関数 本体に yield を含む関数 def f(): yield ... —
ジェネレータ ジェネレータ関数を呼んだ戻り値(イテレータの一種) g = f() ×(1回きり)
ジェネレータ式 1行で書くジェネレータ (x * 2 for x in data) ×(1回きり)
非同期ジェネレータ async def の中で yield async for で回す ×(1回きり)
やりたいこと 書き方
次の値を1つ取る next(g)/next(g, 既定値)
先頭n件だけ取る itertools.islice(g, n)
複数をつなげる itertools.chain(a, b)/yield from a
n件ずつまとめる itertools.batched(g, n)(3.12+)
別のジェネレータに任せる yield from sub()
外から値を渡す g.send(値)(最初は next(g))
中に例外を投げ込む g.throw(例外)
途中で終わらせる g.close()(3.13+は return 値を返す)
return の値を受け取る StopIteration.value/x = yield from sub()
合計・最大・存在確認 sum(...)・max(...)・any(...) にそのまま渡す

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Pythonジェネレータとyield|使い所とメモリ比較コード集」

イテレータとジェネレータの関係

ジェネレータは、イテレータを簡単に作るための仕組みです。 イテレータは __iter__ と __next__ を持ち、値がなくなると StopIteration を送出するオブジェクトです。ジェネレータ関数を呼ぶと、この2つを自動で備えたオブジェクトが返ります。

flowchart LR
    A[イテラブル<br/>list・str・ファイル] -->|iter で取り出す| B[イテレータ<br/>__next__ を持つ]
    C[ジェネレータ関数<br/>def ... yield] -->|呼び出す| D[ジェネレータ]
    E[ジェネレータ式<br/>x for x in ...] --> D
    D -->|イテレータの一種| B

yieldで一時停止する動きを確かめる

# basics.py(Python 3.8+)
from collections.abc import Iterator, Generator, Iterable

def count_up(n):
    print("  開始")
    i = 1
    while i <= n:
        print(f"  yield {i} の直前")
        yield i
        i += 1
    print("  終了")

g = count_up(2)
print(type(g).__name__, isinstance(g, Iterator), isinstance(g, Generator))
print("next →", next(g))
print("next →", next(g))
try:
    next(g)
except StopIteration:
    print("StopIteration")
print(iter(g) is g)
lst = [1, 2]
print(isinstance(lst, Iterable), isinstance(lst, Iterator), iter(lst) is lst)

実行結果(Python 3.14.7):

generator True True
  開始
  yield 1 の直前
next → 1
  yield 2 の直前
next → 2
  終了
StopIteration
True
True False False

count_up(2) を呼んだ時点では「開始」が表示されていない点に注目してください。本体は最初の next() で動き出し、yield で値を返して一時停止し、次の next() で続きから再開します。最後まで進むと StopIteration が送出され、for 文はこれを合図にループを終えます。

iter(g) is g が True なのは、ジェネレータが自分自身をイテレータとして返すからです。一方リストは iter() のたびに新しいイテレータを作るので、何度でも回せます。

クラスで書くイテレータとの比較

# iterclass.py
class Countdown:                       # イテレータをクラスで書く場合
    def __init__(self, start):
        self.n = start
    def __iter__(self):
        return self
    def __next__(self):
        if self.n <= 0:
            raise StopIteration
        self.n -= 1
        return self.n + 1

def countdown(start):                  # 同じものをジェネレータ関数で
    while start > 0:
        yield start
        start -= 1

class Inventory:                       # 何度でも回せるイテラブル
    def __init__(self, items):
        self.items = items
    def __iter__(self):                # __iter__ をジェネレータにする
        for name in self.items:
            yield name

print(list(Countdown(3)), list(countdown(3)))
inv = Inventory(["ペン", "ノート"])
print(list(inv), list(inv))
[3, 2, 1] [3, 2, 1]
['ペン', 'ノート'] ['ペン', 'ノート']

クラスで12行かかるイテレータが、ジェネレータ関数なら4行で書けます。また、__iter__ をジェネレータにすると、何度でも回せるクラスになります(回すたびに新しいジェネレータが作られるため)。

ジェネレータ関数とジェネレータ式の使い分け

比べる点 ジェネレータ関数 ジェネレータ式
書き方 def f(): ... yield x (式 for x in ... if ...)
複数行の処理・try・with 書ける 書けない
状態(合計・前の値)を持つ 得意 不向き
send・return の値 使える 使わない
向いている場面 ファイル読み込み、パイプラインの各段 sum・max・any に渡す一時的な計算

ジェネレータ式の書き方は、別記事「Python内包表記」で早見表にまとめています。

リストとのメモリ比較(実測)

100万個の値を、リストは約8MB(中身を含めると約39MB)使い、ジェネレータは約200バイトで済みました。

# mem.py(Python 3.8+)
import sys, tracemalloc

N = 1_000_000

def squares_list(n):
    return [i * i for i in range(n)]

def squares_gen(n):
    for i in range(n):
        yield i * i

print("getsizeof リスト    :", f"{sys.getsizeof(squares_list(N)):,} バイト")
print("getsizeof ジェネレータ:", f"{sys.getsizeof(squares_gen(N)):,} バイト")

for label, make in [("リスト", squares_list), ("ジェネレータ", squares_gen)]:
    tracemalloc.start()
    total = sum(make(N))
    current, peak = tracemalloc.get_traced_memory()
    tracemalloc.stop()
    print(f"{label:<8} sum={total}  ピーク {peak / 1024:10,.1f} KiB")

実行結果(Python 3.14.7。3.11.15でも同じ値でした):

getsizeof リスト    : 8,448,728 バイト
getsizeof ジェネレータ: 208 バイト
リスト      sum=333332833333500000  ピーク   39,497.1 KiB
ジェネレータ   sum=333332833333500000  ピーク        0.2 KiB
測り方 何を測るか リスト ジェネレータ
sys.getsizeof オブジェクト本体だけ(リストは要素への参照の配列) 約8.4MB 208バイト
tracemalloc のピーク 処理中にPythonが確保したメモリの最大値(要素の整数も含む) 約38.6MiB 約0.2KiB

sys.getsizeof は中身の大きさを含まないため、実際のメモリ使用量を見たいときは tracemalloc のピーク値を使うのが確実です。

大きなファイルを1行ずつ処理する

ファイルオブジェクトはそれ自体がイテレータなので、for line in f で1行ずつ読めます。 次のコードで作業用のログファイル(200万行、87MB)を作り、readlines() と比べました。

# make_log.py:作業用の大きなログファイルを作る
import random
random.seed(1)
levels = ["INFO"] * 8 + ["WARN", "ERROR"]
items = ["ノート", "ペン", "付箋", "ファイル", "テープ"]
with open("access.log", "w", encoding="utf-8") as f:
    for i in range(2_000_000):
        f.write(f"2026-09-30T{i % 24:02d}:{i % 60:02d}:00 {random.choice(levels)} "
                f"item={random.choice(items)} qty={random.randint(1, 9)}\n")
$ ls -lh access.log
-rw-r--r-- 1 root root 87M Oct  1 23:09 access.log
$ head -3 access.log
2026-09-30T00:00:00 INFO item=テープ qty=2
2026-09-30T01:01:00 INFO item=ノート qty=8
2026-09-30T02:02:00 INFO item=ファイル qty=7
# bigfile.py
import time, tracemalloc

def run(label, fn):
    tracemalloc.start()
    t = time.perf_counter()
    result = fn()
    sec = time.perf_counter() - t
    _, peak = tracemalloc.get_traced_memory()
    tracemalloc.stop()
    print(f"{label:<22} 結果={result:,}  {sec:5.2f} 秒  ピーク {peak / 1024 / 1024:7.2f} MiB")

def with_readlines():
    with open("access.log", encoding="utf-8") as f:
        lines = f.readlines()              # 全行をリストに読み込む
    return sum(1 for line in lines if " ERROR " in line)

def with_iteration():
    with open("access.log", encoding="utf-8") as f:
        return sum(1 for line in f if " ERROR " in line)   # 1行ずつ読む

run("readlines()(全行)", with_readlines)
run("for line in f(1行ずつ)", with_iteration)

実行結果(Python 3.14.7):

readlines()(全行)        結果=200,435   1.72 秒  ピーク  279.31 MiB
for line in f(1行ずつ)    結果=200,435   1.07 秒  ピーク    0.17 MiB

同じ結果を、ピークメモリ約279MiB→約0.17MiBで得られました。 ファイルが大きくなっても、1行ずつ読む方式ならメモリ使用量はほぼ一定です。

パイプラインを組む(読み込み→フィルタ→変換→集計)

ジェネレータをつなげると、各段が1行ずつ受け渡しながら動くパイプラインになります。 それぞれの関数は短く、単体でテストしやすいのも利点です。

# pipeline.py(Python 3.9+:str.removeprefix を使用)
import time, tracemalloc
from collections import Counter
from itertools import islice

def read_lines(path):                       # 1. 読み込み
    with open(path, encoding="utf-8") as f:
        for line in f:
            yield line.rstrip("\n")

def only_errors(lines):                     # 2. フィルタ
    for line in lines:
        if " ERROR " in line:
            yield line

def parse(lines):                           # 3. 変換
    for line in lines:
        _, _, item, qty = line.split(" ")
        yield item.removeprefix("item="), int(qty.removeprefix("qty="))

def total_by_item(records):                 # 4. 集計
    c = Counter()
    for item, qty in records:
        c[item] += qty
    return c

tracemalloc.start()
t = time.perf_counter()
print("先頭3件:", list(islice(parse(only_errors(read_lines("access.log"))), 3)))
result = total_by_item(parse(only_errors(read_lines("access.log"))))
_, peak = tracemalloc.get_traced_memory()
print(dict(result.most_common()))
print(f"{time.perf_counter() - t:.2f} 秒  ピーク {peak / 1024:.1f} KiB")

実行結果(Python 3.14.7):

先頭3件: [('ノート', 8), ('テープ', 7), ('付箋', 8)]
{'ペン': 201461, 'ノート': 201415, '付箋': 200967, 'テープ': 200838, 'ファイル': 200516}
2.50 秒  ピーク 171.9 KiB
flowchart LR
    A[read_lines<br/>1行読む] -->|1行| B[only_errors<br/>ERRORだけ通す]
    B -->|1行| C[parse<br/>品名と数量に分解]
    C -->|1件| D[total_by_item<br/>Counterで合計]

87MBのファイル全体を処理しても、ピークは約172KiBでした。 islice で先頭3件だけ取り出すと、残りの行は読まれません。動作確認のときに便利です。

itertoolsと組み合わせる

itertools の関数はどれもイテレータを受け取ってイテレータを返すので、ジェネレータと自然につながります。

# itertools_demo.py(batched は 3.12+、strict は 3.13+)
from itertools import islice, chain, batched, count, takewhile

def order_ids():
    n = 1000
    while True:              # 無限に続くジェネレータ
        yield f"ORD-{n}"
        n += 1

print(list(islice(order_ids(), 3)))
print(list(islice(order_ids(), 5, 8)))
print(list(chain(["ペン", "ノート"], (s for s in ["付箋"]))))
for batch in batched(islice(order_ids(), 7), 3):
    print("まとめて登録:", batch)
print(list(takewhile(lambda x: x < 20, (n * n for n in count(1)))))
try:
    list(batched(range(7), 3, strict=True))
except ValueError as e:
    print("ValueError:", e)

実行結果(Python 3.14.7):

['ORD-1000', 'ORD-1001', 'ORD-1002']
['ORD-1005', 'ORD-1006', 'ORD-1007']
['ペン', 'ノート', '付箋']
まとめて登録: ('ORD-1000', 'ORD-1001', 'ORD-1002')
まとめて登録: ('ORD-1003', 'ORD-1004', 'ORD-1005')
まとめて登録: ('ORD-1006',)
[1, 4, 9, 16]
ValueError: batched(): incomplete batch
関数 役割 対応版
islice(it, n)/islice(it, start, stop) 先頭n件・範囲を取る(スライスの代わり) 全版
chain(a, b, ...) 複数をつなげる 全版
batched(it, n) n件ずつタプルにまとめる(DBへのまとめて登録など) 3.12+(strict は3.13+)
count(start) 無限に数える 全版
takewhile(条件, it) 条件を満たす間だけ取る 全版
tee(it, n) 1つのイテレータをn本に分ける 全版

Python 3.11で batched を使うと ImportError: cannot import name 'batched' from 'itertools' になります。3.11以前では islice を使って同じ動きを書けます。

from itertools import islice

def batched_compat(iterable, n):    # 3.11以前向け
    it = iter(iterable)
    while batch := tuple(islice(it, n)):
        yield batch

yield fromで別のジェネレータに任せる

yield from イテラブル は、中身を1つずつ yield するのと同じ動きをし、さらにサブジェネレータの return の値を受け取れます。

# yieldfrom.py(Python 3.8+)
def categories():
    yield from ["文具", "収納"]          # イテラブルをそのまま流す
    yield from sub_items()

def sub_items():
    yield "ペン"
    yield "ノート"
    return "sub完了"                     # return の値

def outer():
    result = yield from sub_items()      # サブジェネレータの return 値を受け取る
    print("  受け取った値:", result)

print(list(categories()))
print(list(outer()))

g = sub_items()
next(g); next(g)
try:
    next(g)
except StopIteration as e:
    print("StopIteration.value =", e.value)

def walk(tree):                           # 入れ子の構造を平らにする
    for node in tree:
        if isinstance(node, list):
            yield from walk(node)
        else:
            yield node
print(list(walk(["A", ["B", ["C", "D"]], "E"])))

実行結果(Python 3.14.7):

['文具', '収納', 'ペン', 'ノート']
  受け取った値: sub完了
['ペン', 'ノート']
StopIteration.value = sub完了
['A', 'B', 'C', 'D', 'E']

ジェネレータ内の return 値 は、StopIteration.value として外に渡されます。 for 文や list() はこの値を使わないので、受け取りたいときは yield from の戻り値か、next() と except StopIteration as e を使います。yield from は send・throw もサブジェネレータにそのまま中継します。

send・throw・closeで外から操作する

send(値) は yield 式の戻り値として値を渡しながら再開し、throw(例外) は止まっている yield の位置で例外を発生させ、close() は終了させます。

# send.py
def running_average():
    total, count, avg = 0, 0, None
    while True:
        value = yield avg                 # send() で受け取った値が入る
        total += value
        count += 1
        avg = total / count

avg = running_average()
print(next(avg))                          # 最初の yield まで進める
print(avg.send(10))
print(avg.send(20))
print(avg.send(60))

g = running_average()
try:
    g.send(10)
except TypeError as e:
    print("TypeError:", e)

def worker():
    try:
        while True:
            try:
                task = yield
                print("  処理:", task)
            except ValueError as e:
                print("  throw で受け取った:", e)
    finally:
        print("  後片付け(finally)")

w = worker()
next(w)
w.send("在庫チェック")
w.throw(ValueError("入力が不正です"))
w.send("棚卸し")
w.close()
print("close 後の状態:", w.gi_frame is None)

def counter():
    n = 0
    try:
        while True:
            yield
            n += 1
    except GeneratorExit:
        return n                          # 3.13+ では close() がこの値を返す

c = counter()
next(c); next(c); next(c)
print("close() の戻り値:", c.close())

実行結果(Python 3.14.7):

None
10.0
15.0
30.0
TypeError: can't send non-None value to a just-started generator
  処理: 在庫チェック
  throw で受け取った: 入力が不正です
  処理: 棚卸し
  後片付け(finally)
close 後の状態: True
close() の戻り値: 2

Python 3.11.15では最後の行が close() の戻り値: None でした。3.13から、GeneratorExit を受けて return した値を close() が返すようになっています。

メソッド 動き よくある使い方
next(g) 次の yield まで進める(send(None) と同じ) 値を取り出す、最初の起動
g.send(値) yield 式の結果として値を渡して再開 移動平均などの状態を持つ計算
g.throw(例外) 止まっている yield の位置で例外を発生 中断の合図、エラーの通知
g.close() GeneratorExit を発生させて終了 途中でやめるときの後片付け

最初の send の前に next(g)(または g.send(None))が必要です。忘れると上のとおり TypeError: can't send non-None value to a just-started generator になります。

つまずきやすいポイント

一度しか回せない・len()や添字が使えない

# pitfalls.py
def items():
    yield "ペン"
    yield "ノート"

g = items()
print("1回目:", list(g))
print("2回目:", list(g))
print("in 演算子:", "ペン" in items(), "ペン" in g)
try:
    len(items())
except TypeError as e:
    print("TypeError:", e)
try:
    items()[0]
except TypeError as e:
    print("TypeError:", e)
1回目: ['ペン', 'ノート']
2回目: []
in 演算子: True False
TypeError: object of type 'generator' has no len()
TypeError: 'generator' object is not subscriptable

使い切ったジェネレータはエラーにならず空を返すので、2回目の結果が空のときはここを疑います。何度も使うなら list() にするか、ジェネレータ関数を呼び直します。件数が必要なら sum(1 for _ in g)、先頭の値なら next(g) を使います。in 演算子も、見つかるまで値を消費する点に注意します。

例外の伝わり方

def broken():
    yield 1
    raise StopIteration          # ジェネレータの中で StopIteration を送出
try:
    list(broken())
except RuntimeError as e:
    print("RuntimeError:", e)

def lazy_check(values):
    if not values:
        raise ValueError("空です")   # 呼び出した時点では実行されない
    yield from values
g = lazy_check([])
print("ジェネレータは作れた:", type(g).__name__)
try:
    next(g)
except ValueError as e:
    print("next() で初めて ValueError:", e)

def parse_qty(rows):
    for r in rows:
        yield int(r)
gen = parse_qty(["1", "x", "3"])
print(next(gen))
try:
    next(gen)
except ValueError as e:
    print("ValueError:", e)
print("例外のあと:", list(gen))
RuntimeError: generator raised StopIteration
ジェネレータは作れた: generator
next() で初めて ValueError: 空です
1
ValueError: invalid literal for int() with base 10: 'x'
例外のあと: []
現象 理由 対処
RuntimeError: generator raised StopIteration ジェネレータ内の StopIteration は RuntimeError に置き換わる(PEP 479) 終わりたいときは return と書く
引数チェックのエラーが遅れて出る 本体は最初の next() まで動かない チェックを普通の関数に分け、中でジェネレータを返す
例外のあと残りが取れない 例外が外に出たジェネレータは終了する 1件の失敗で止めたくないなら、ジェネレータ内で try/except して印をつけて yield

引数チェックをすぐに行いたい場合は、次のように分けます。

def lazy_check(values):
    if not values:
        raise ValueError("空です")    # 呼んだ瞬間にチェックされる
    return _iter_values(values)

def _iter_values(values):
    yield from values

with の外で回すとファイルが閉じている

def lines_wrong(path):
    with open(path, encoding="utf-8") as f:
        return (line for line in f)    # ジェネレータ式を返した時点で with を抜ける

この関数の戻り値を回すと ValueError: I/O operation on closed file. になります。with の中で yield する(上の read_lines のように書く)と、最後まで読み終えるかジェネレータが閉じられるまでファイルが開いたままになります。

非同期ジェネレータの最小例

async def の中で yield を使うと非同期ジェネレータになり、async for で回します。 ページごとにAPIを呼ぶような、待ち時間をはさみながら値を順に返す処理に向いています。

# agen.py(Python 3.8+)
import asyncio

async def fetch_pages(n):
    for page in range(1, n + 1):
        await asyncio.sleep(0.1)          # API呼び出しの待ち時間の代わり
        yield {"page": page, "items": page * 10}

async def main():
    async for p in fetch_pages(3):
        print(p)
    print([p["items"] async for p in fetch_pages(2)])

asyncio.run(main())

実行結果(Python 3.14.7):

{'page': 1, 'items': 10}
{'page': 2, 'items': 20}
{'page': 3, 'items': 30}
[10, 20]

非同期ジェネレータでは yield from は使えないため、async for x in sub(): yield x と書きます。asyncioそのものの書き方は、別記事「Python asyncioの使い方」で解説しています。

contextlib.contextmanagerとの関係

@contextmanager は、yield が1回だけのジェネレータ関数を with 文で使えるようにするデコレータです。 yield の前が with に入るときの処理、後が出るときの処理になり、yield した値が as の変数に入ります。

# ctx.py(Python 3.8+)
import time
from contextlib import contextmanager

@contextmanager
def timer(label):
    start = time.perf_counter()
    print(f"[{label}] 開始")
    try:
        yield start                         # with ... as の値になる
    finally:
        print(f"[{label}] 終了 {time.perf_counter() - start:.2f} 秒")

with timer("棚卸し") as t0:
    time.sleep(0.1)

try:
    with timer("エラー時"):
        raise KeyError("備品ID")
except KeyError as e:
    print("例外は外に伝わる:", e)

実行結果(Python 3.14.7):

[棚卸し] 開始
[棚卸し] 終了 0.10 秒
[エラー時] 開始
[エラー時] 終了 0.00 秒
例外は外に伝わる: '備品ID'

with ブロック内の例外は、yield の位置に投げ込まれます(内部で throw() が使われています)。そのため、後片付けを確実に行うには yield を try/finally で囲みます。

ジェネレータを使うか、リストにするかの判断表

状況 おすすめ 理由
大きなファイル・DBの結果を順に処理 ジェネレータ メモリがほぼ一定
結果を1回だけ順に使う ジェネレータ リストを作る手間が不要
無限に続く値(連番、ポーリング) ジェネレータ リストでは表せない
件数・添字・並べ替えが必要 リスト len・[i]・sort が使える
同じ結果を何度も使う リスト ジェネレータは1回きり
少量のデータで手軽に確認 リスト 表示やデバッグがしやすい

よくある質問

Q. yieldとreturnの違いは何ですか? A. return は値を返して関数を終わらせ、yield は値を返して一時停止します。 ジェネレータ関数の中の return 値 は、StopIteration.value として渡される「終わりの合図」になります。

Q. ジェネレータの中身を確認したいときは? A. list(g) で中身を表示できますが、その時点で使い切ります。list(itertools.islice(g, 5)) で先頭だけ確認し、本番の処理には新しく作り直したジェネレータを渡すと安全です。

Q. ジェネレータはリストより遅いですか? A. 今回の87MBのファイルでは、1行ずつ読むほうが1.07秒、readlines() が1.72秒でした。少量で何度も使う場合はリスト、大量・1回きりならジェネレータを目安にするとよいでしょう。

Q. 型ヒントはどう書きますか? A. 値を返すだけなら Iterator[int]、send・return も使うなら Generator[int, float, str](yieldする型、sendする型、returnする型)と書きます。3.13以降は後ろ2つに既定値(None)があり、Generator[int] と書けます。

まとめ

  • ジェネレータは yield で値を1つずつ返すイテレータ。呼んだ時点では本体は動かず、next() で進みます。
  • 実測では100万件でリスト約38.6MiB→ジェネレータ約0.2KiB、87MBのファイルもピーク約0.17MiBで処理できました。
  • 読み込み→フィルタ→変換→集計をジェネレータでつなぐと、短い関数の組み合わせで大量データを扱えます。
  • islice・chain・batched(3.12+) と組み合わせると、先頭だけ・連結・まとめて処理が1行で書けます。
  • yield from は委譲と return 値の受け取り、send・throw・close は外からの操作に使います(3.13+は close() が値を返します)。
  • 一度しか回せない・len() が使えない・エラーは最初の next() で出る、の3点を押さえておくと迷いません。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Pythonジェネレータとyield|使い所とメモリ比較コード集」

株式会社RJCでは、Pythonのジェネレータを使ったデータ処理を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?