BETA

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

投稿日:2019-06-19
最終更新:2019-06-19

はじめに

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

※以下の記事で使用している内包表記内での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  

まとめ

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

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@watosarの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!