LoginSignup
0

More than 3 years have passed since last update.

def文及びlambda式不使用で関数を作る挑戦

Last updated at Posted at 2019-06-18

はじめに

初心者プログラマーながらアウトプットにも挑戦してみようと思い記事を書くことにしました。

※以下の記事で使用している内包表記内でのyield式の使用は3.7で非推奨、3.8以降で動かないことが判明しています。参照

環境

• python3.6.1

TL;DR

位置引数を受けるものなら標準ライブラリの使用まで妥協し実現できた。
キーワード引数の受け取り方は不明

詳細

この試みを思い立ったきっかけは何処かでyieldを式として使えるという記事を見たことです。
と言うわけで位置引数一つを取る事が可能になりました。

next(
    func for func in (
        (
            0 for _args, _return in iter([[], [None]].copy,None)
            if _args.append((yield _return[0])) or [[
                0 for arg in _args 
                for _return[0] in (arg,) if not print('arg is', arg)
            ]] and _args.clear()
        ),
    ) if [next(func)]
).send

次に必要なのは複数の引数をどうにかしてこれに渡す事です。
max/min関数が誂え向きでした。と言う訳で複数の位置引数を取れるようになります。
functool.partialで小細工をして、

next(
    __import__('functools').partial(
        max, _return,
        key = next(
            func for func in ((
                0
                for _ in iter(int,1)
                if _args.append((yield 0)) or 
                ((_return.__setitem__(0,None) or [[
                    0 for _return, *args in (_args,)
                    for _return[0] in (args,) if not print('args are', args)
                ]] and _args.clear())
                if ((_args[0] is _return and _args.count(_return)==1 or _args.clear()) and len(_args)==_count) else _return.__setitem__(0,'error'))
            ),) if [next(func)]
        ).send
    )
    for _return, _count, _args in ((['error'], 1+2, []),)
)

以下のコードはこれらを利用し、再帰処理的に階差計算をするものです。
そのままやると、動かしている最中のジェネレーターにsendは送れないと怒られるので毎度生成される様にしてあります。

next(func for func in ((0 for _args, _return in iter([[], [None]].copy,None)if _args.append((yield _return[0])) or [[0 for N in _args for _return[0] in (next(func for func in ((0 for _args, _return in iter([[], [None]].copy,None)if _args.append((yield _return[0])) or [[0 for f in _args for _return[0] in (f()(f, N)[0],)]] and _args.clear()),) if [next(func)]).send((next(__import__('functools').partial(max, _return,key = next(func for func in ((0for _ in iter(int,1)if _args.append((yield 0)) or ((_return.__setitem__(0,None) or [[0 for _return, f, n in (_args,)for _return[0] in (1 if n==1 else f()(f, n-1)[0]*n,)]] and _args.clear())if ((_args[0] is _return and _args.count(_return)==1 or _args.clear()) and len(_args)==_count) else _return.__setitem__(0,'error'))),) if [next(func)]).send)for _return, _count, _args in ((['error'], 1+2, []),)) for _ in range(N)).__next__),) ]] and _args.clear()),) if [next(func)]).send

階乗といえば個人的にはreduce(int.__mul__, range(1,6))ってするのが好きです

まとめ

def文又はlambda式アレルギーのあるお子様のいるご家庭でもpythonは安心してお使いいただけます。
難しい事がわからなくともワンライナーはパズルとして気軽に挑戦し、楽しめるので暇つぶしに最適です。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0