見出し画像

Python資格取得への道のり 15日目

・モジュールの宣言であるimportでは*を使わない???

14日の最後に行ったhuman.pyのフォルダ内に「animal.py」を作成し、呼び出しファイルでhuman.pyを「animal.py」に変更。

from lesson_package.talk import animal

r = animal.sing()

print(r)
print(animal.cry())

#ahishdoashdaiwh:poqw:heipq
#aihihaihihsdpi:hahqwe!aihihaihihsdpi:hahqwe!

最初の行を一部変更して、

from lesson_package.talk import *

r = animal.sing()

print(r)
print(animal.cry())

#エラ〜

importの後を「*」にしてみるとエラ〜。

ではどうすれば?
animal.pyとhuman.pyの2つのモジュールが入っているパッケージ内もう1つのファイル__init__.py内のコードを下記に修正

__all__ = ['animal']

それだけで、同じコードなのに実行できるようになります。

from lesson_package.talk import *

r = animal.sing()

print(r)
print(animal.cry())

#ahishdoashdaiwh:poqw:heipq
#aihihaihihsdpi:hahqwe!aihihaihihsdpi:hahqwe!

human.pyを使いたい場合は、同じように__init__.py内に__all__を使用して記載することで使用できる。

しかし、これを毎回するのは非効率的ですので、基本的には推奨されていません。

・Importエラーの対処

try:
   from lesson_package import utils
except ImportError:
   from lesson_package.tools import utils

print(utils.say_twice('help'))

以前、utilsはlesson_packageの配下にありましたが、さらに下層のtoolsの配下に置くようになりました。

このように以前のパッケージと現在のパッケージでモジュールが置いてあるところが異なる場合はtry-except文(Importエラー)が使えます。

try:
   #以前のパッケージ
except ImportError:
   #現行のパッケージ

#実行したい文

上記のような感じで書いておくと、エラーを返さず実行できます。

・setup.pyでパッケージ化して配布する

setup.pyを作成(①)して、他の人に配布する(②)ことができます。

setup.pyは自分で作成 or PycharmならToolsの中にある「create setup.py」で作成できる。

作成できたsetup.pyを元に配布の準備をする。

CLIから下記コマンド

python setup.py sdist

もしくは、PycharmならToolsの中にある「run setup.py task...」でsdistを選択。

そうすると「 MANIFEST」と「distフォルダ」が作成される。

「distフォルダ」内にあるtar.gzファイルを配信することで他者はパッケージとして使用できる。

・組み込み関数

Pythonに元々あるライブラリーについて

元々 print や nextというものは「builtins」のライブラリーの中にあるもの。

本当であれば下記のようなコードが必要ですが、すでに組み込まれているため不要になります。

import builtins

builtins.print()

組み込み関数の「builtins」にある「sorted」を使っています。

ランキングを点数の高い順に並び替えたいですが、下記コードですと
思うようにうまくいきません。

ranking = {
   'A': 100,
   'B': 85,
   'C': 95
}

for x in ranking:
   print(x)

#A
#B
#C

ではどうすれば?下記の1文が重要となります。

ranking = {
   'A': 100,
   'B': 85,
   'C': 95
}

print(ranking.get('A'))

#100

それを応用して

ranking = {
   'A': 100,
   'B': 85,
   'C': 95
}
print(sorted(ranking, key=ranking.get))

#['B', 'C', 'A']

でも、これでは逆だ。sortedのオプション引数を使い、「reverse=True」を使って、、、

ranking = {
   'A': 100,
   'B': 85,
   'C': 95
}
print(sorted(ranking, key=ranking.get, reverse=True))

#['A', 'C', 'B']

これで予定通りの並び替えになりました。

・標準ライブラリ

組み込み関数はすでに組み込まれている。

一方で、標準ライブラリは組み込まれていないからimportで自分で組み込んでいく。

よく使わられるcollectionsのdefaultdictを標準ライブラリから使ってみます。

まずはdefaultdictなしバージョン。
sにアルファベットの何が何個入っているのか確認するコード

s = "aihojodja;dm;aksndipahwieoqjwe:k"

d = {}
for x in s:
    if x not in d:
        d[x] = 0
    d[x] += 1
print(d)

#{'a': 4, 'i': 3, 'h': 2, 'o': 3, 'j': 3, 'd': 3, ';': 2, 'm': 1, 'k': 2, 's': 1, 'n': 1, 'p': 1, 'w': 2, 'e': 2, 'q': 1, ':': 1}

他にはsetdefaultやdefaultdictが使える。

s = "aihojodja;dm;aksndipahwieoqjwe:k"

d = {}
for x in s:
    if x not in d:
        d[x] = 0
    d[x] += 1
print(d)

d = {}
for x in s:
    d.setdefault(x, 0)
    d[x] += 1
print(d)

from collections import defaultdict

d = defaultdict(int)

for x in s:
    d[x] += 1
print(d)

#{'a': 4, 'i': 3, 'h': 2, 'o': 3, 'j': 3, 'd': 3, ';': 2, 'm': 1, 'k': 2, 's': 1, 'n': 1, 'p': 1, 'w': 2, 'e': 2, 'q': 1, ':': 1}
#{'a': 4, 'i': 3, 'h': 2, 'o': 3, 'j': 3, 'd': 3, ';': 2, 'm': 1, 'k': 2, 's': 1, 'n': 1, 'p': 1, 'w': 2, 'e': 2, 'q': 1, ':': 1}
#defaultdict(<class 'int'>, {'a': 4, 'i': 3, 'h': 2, 'o': 3, 'j': 3, 'd': 3, ';': 2, 'm': 1, 'k': 2, 's': 1, 'n': 1, 'p': 1, 'w': 2, 'e': 2, 'q': 1, ':': 1})

「from collections import defaultdict」

上記のように標準ライブラリは読み込みが必要!

・サードパーティのライブラリ

pip install サードパーティのライブラリ

上記でインストールを完了することができ、それを使用したい場合は「from」でライブラリ、そして「import」でモジュールを指定する。

from termcolor import colored

print('test')

print('test', 'red')

print(colored('test', 'red'))

#test
#test red
#test(赤色)

サードパーティのライブラリがわからなくなったらpypiのHPや下記コードでわかります。

print(help(colored))

・importする際の記述の仕方

標準ライブラリを下記のようにインポートすることは可能。

import collections, sys, os 

でも推奨されていなく、下記が推奨です。またアルファベット順が良い。

import collections 
import os 
import sys

では、サードパーティのものや同僚が作ったものに関してはどうすればいいのか?

import collections 
import os 
import sys

import termcolor

import lesson_package

import config

#順番として
#標準ライブラリ
#スペース
#サードパーティのライブラリ
#スペース
#同僚や会社の中でのライブラリ
#スペース
#自分が作成したライブラリ(ローカル)

では、ライブラリはどこに保存されているのか場所を知りたい場合は下記コマンドで知れる。

print(collections.__file__)
print(termcolor.__file__)
print(lesson_package.__file__)

またどの順番でライブラリを読んでいくかは下記コマンドでわかる

print(sys.path)

順序として
①ローカル
②標準ライブラリ
③サードパーティのライブラリの順番

そのため標準ライブラリの内容をローカルに作ってしまうと、それが優先して読み込まれてしまうので注意が必要

・__name__と__main__

print(__name__)

#__main__
#自分が実行しているファイルがメインのスクリプトであるということ

もし、モジュールを読み込んでその先にも同様に「print(__name__)」が記載されていたらどうなるのか。

下記モジュールの中身

print('config :',__name__)

実行するファイル(スクリプト)の中身

import config

print(__name__)

#config : config
#__main__

これはimportで読み込んだ先にprintがあったため、それを返してしまいます。。importだけではない「config : config」

そしてスクリプトに記載されていたprint文の出力として「__main__」を返したということ

これを利用して、他者に読み込まれたくないコードには下記を書いていることがある。

・他者にモジュールとして読み込まれるファイルについて

import config

from lesson_package.talk import animal

print(__name__)

新しく「animal」というモジュールを読み込みます。
もし、animalにprint等が書いてあった場合は、これだけで実行されてしまいます。

しかし結果としては下記となりました。

config : config
__main__

animalにはどう書かれていたのでしょうか。

#絶対パス
# from lesson_package.tools import utils
#相対パス
from ..tools import utils

def sing():
   return 'ahishdoashdaiwh:poqw:heipq'

def cry():
   return utils.say_twice('aihihaihihsdpi:hahqwe')

if __name__ ==  '__main__':
   print(sing())
   print('animal;', __name__)

printは書かれていたものの、「if __name__ == '__main__':」という形でanimal.pyがスクリプトではないためprintが実行されなかったということになります。
もしスクリプト(if __name__ == '__main__':)ならprintは実行されます。

他者からモジュールとして使用される可能性がある場合は下記のようにコードを記載しておくことが重要です。

def main():
   スクリプト時に実行したいアクション


if __name__ == '__main__':
   main()   

今日はここまで。

溜まっていた宿題を終わらせた感があります。

明日からは「クラス」

ここまで終われば一通り試験範囲も終わり、座学に突入です。

いいなと思ったら応援しよう!