いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

CLionでmakefileをサポートしてくれるプラグイン (JetBrains, CLion, Makefile Support)

概要

CLionさん、とても便利で重宝しているのですが、現在のところ CMake しかサポートしてくれていないのがちょっとネックでした。

まあ、CMakeLists.txt ちょっと頑張ったら行けるのですが、大抵のC言語プロジェクトってmakefileがついています。

で、以下のような素敵なプラグインがあることを発見。忘れない内にメモメモ。

github.com

Makefile support plugin for IntelliJ IDEA

素晴らしいです。超感謝です。

設定は、設定ウィンドウのプラグインのところで、「makefile」って打ち込めば普通に出てきます。

後はインストールして再起動したら、makefileがサポートされます。

ちゃんと「Structure」ビューに構造でてきたり、マウス一発で実行できたり最高です。

プラグイン自体は、kotlin で記述されていますね。


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。

Pythonメモ-47 (結果の型を特定の値の型と一致させる) (python3, type, coerce)

概要

Fluent Python ―Pythonicな思考とコーディング手法

Fluent Python ―Pythonicな思考とコーディング手法

  • 作者: Luciano Ramalho,豊沢聡,桑井博之,梶原玲子
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2017/10/07
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

に書いてあった小ネタ。なるほどって思ったので忘れない内にメモ。

2つの数値を受け取る処理があって、中で処理して結果を返すときに

基本 python に任せておけば、いいようにやってくれるのですが

型を揃えたいときがあります。

たとえば、上に挙げた書籍「Fluent Python」のサンプルコードほぼパクリですが

以下のようなジェネレータ関数があるとして

def my_range1(begin, step, end=None):
    result = begin
    forever = end is None

    while forever or result < end:
        yield result
        result += step

以下のように使うと

    gen1 = my_range1(1, 2, 5)
    for x in gen1:
        print(f'gen1={x}({type(x)})')

当然結果は

gen1=1(<class 'int'>)
gen1=3(<class 'int'>)

となります。

でも、以下のように呼び出すと

    gen1 = my_range1(1, 2.0, 5.0)
    for x in gen1:
        print(f'gen1={x}({type(x)})')

結果は

gen1=1(<class 'int'>)
gen1=3.0(<class 'float'>)

ってなります。これは、beginが int で、step を float で指定しているため

最初の yield では、begin の値がそのまま生成されるため、int で、次からは step を加算した値が生成されるため float となります。

このままでいい場合もありますし、最初の yield の値から float で揃えたい場合もあります。

で、上の本に記載されていたのを使うと以下のようになります。

def my_range2(begin, step, end=None):
    result = type(begin + step)(begin)
    forever = end is None

    while forever or result < end:
        yield result
        result += step

変更点は、以下の部分です。

result = type(begin + step)(begin)

これ、最初「何やってるんだろう?」って思ったのですが、要は 一旦足してみてその結果の型で結果の初期値を生成ってやってるんですね。

なるほどぉって思いました。

で、このようにすると、結果が以下のようになります。

    gen2 = my_range2(1, 2, 5)
    for x in gen2:
        print(f'gen2={x}({type(x)})')

結果は

gen2=1(<class 'int'>)
gen2=3(<class 'int'>)

となり

    gen2 = my_range2(1, 2.0, 5.0)
    for x in gen2:
        print(f'gen2={x}({type(x)})')

gen2=1.0(<class 'float'>)
gen2=3.0(<class 'float'>)

と、一回目の yield から float になります。

ついでに、decimal.Decimal つかった場合も

    gen1 = my_range1(1, Decimal(2.0), Decimal(5.0))
    for x in gen1:
        print(f'gen1={x}({type(x)})')

    gen2 = my_range2(1, Decimal(2.0), Decimal(5.0))
    for x in gen2:
        print(f'gen2={x}({type(x)})')

以下の結果となります。

gen1=1(<class 'int'>)
gen1=3(<class 'decimal.Decimal'>)
gen2=1(<class 'decimal.Decimal'>)
gen2=3(<class 'decimal.Decimal'>)

サンプルコード

# coding: utf-8

from decimal import Decimal

def my_range1(begin, step, end=None):
    result = begin
    forever = end is None

    while forever or result < end:
        yield result
        result += step


def my_range2(begin, step, end=None):
    result = type(begin + step)(begin)
    forever = end is None

    while forever or result < end:
        yield result
        result += step


if __name__ == '__main__':
    gen1 = my_range1(1, 2, 5)
    for x in gen1:
        print(f'gen1={x}({type(x)})')
    
    gen2 = my_range2(1, 2, 5)
    for x in gen2:
        print(f'gen2={x}({type(x)})')

    print('---------------------------------------')

    gen1 = my_range1(1, 2.0, 5.0)
    for x in gen1:
        print(f'gen1={x}({type(x)})')

    gen2 = my_range2(1, 2.0, 5.0)
    for x in gen2:
        print(f'gen2={x}({type(x)})')

    print('---------------------------------------')

    gen1 = my_range1(1, Decimal(2.0), Decimal(5.0))
    for x in gen1:
        print(f'gen1={x}({type(x)})')

    gen2 = my_range2(1, Decimal(2.0), Decimal(5.0))
    for x in gen2:
        print(f'gen2={x}({type(x)})')

結果は

gen1=1(<class 'int'>)
gen1=3(<class 'int'>)
gen2=1(<class 'int'>)
gen2=3(<class 'int'>)
---------------------------------------
gen1=1(<class 'int'>)
gen1=3.0(<class 'float'>)
gen2=1.0(<class 'float'>)
gen2=3.0(<class 'float'>)
---------------------------------------
gen1=1(<class 'int'>)
gen1=3(<class 'decimal.Decimal'>)
gen2=1(<class 'decimal.Decimal'>)
gen2=3(<class 'decimal.Decimal'>)

となります。

python2 には、coerce って関数があったみたいですが廃止となったみたいですね。

以下も参考になりました。

stackoverflow.com

stackoverflow.com


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。

Pythonメモ-46 (2.x系と3.x系で内包表記内の変数のスコープが違う) (python2, python3, listcomp, 内包表記, 変数スコープ)

概要

pythonに慣れている人は当然な知識なのかもしれませんが、自分用に忘れない内にメモメモ。

Python 2.x 系と python 3.x 系では、内包表記で使用する一時変数のスコープが違うんですね。

python 2.x 系

$ activate py2

(py2) $ python --version
Python 2.7.14 :: Anaconda, Inc.

(py2) $ python
Python 2.7.14 |Anaconda, Inc.| (default, Nov  8 2017, 13:40:45) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> [x for x in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x
9                     # <===== えっ!!??
>>>

2.x 系だと、内包表記内でつかった一時変数が残ってる。

python 3.x 系

$ activate py3

(py3) $ python --version
Python 3.6.3 :: Anaconda, Inc.

(py3) $ python
Python 3.6.3 |Anaconda, Inc.| (default, Nov  8 2017, 15:10:56) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> [x for x in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x                     # <===== 存在しない。(想定通り)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>>

3.x 系だと、想定通りの挙動になっている。


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。