かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Python3 ファイルの絶対パスを取得したい。

os を使う

import os
currnet_dir = os.path.dirname( os.path.abspath(__file__) )

os.path.abspath(__file__) で現在のファイルの絶対パスを取得し、os.path.dirname(path)でファイルのあるディレクトリを取得。
参照: 10.1. os.path — 共通のパス名操作 — Python 2.7.14 ドキュメント

pathlib を使う

Python 3.4 以上

import pathlib
currnet_dir = pathlib.Path(__file__).resolve().parent

pathlib.Path(__file__)で現在のファイルのパスを取得し、resolve()絶対パス化した後に、.parentで親であるディレクトリを取得。という感じでしょうか。
参照: 11.1. pathlib — オブジェクト指向のファイルシステムパス — Python 3.6.5 ドキュメント

ぐぐる検索するとos.pathを使用した例が多く出てきたのですが、Python3.4以上なら新しく追加されたpathlibを使ったほうが良いのかな?と思いました。


[参考]

Python3 Classのメモ

classキーワードに続けて大文字から始まるクラス名を記述してクラスを作成する
クラスからインスタンスを作成する際はnewなどのキーワードは不要
コンストラクタは__init__()で定義する

class Player:
  # constructor
  def __init__(self, name = 'Human'):
    self.name = name

  def say_hello(self, message = 'Yo'):
    print( f'{self.name} says "{message}"' )

player1 = Player('Dog')
player1.say_hello('Woof')
# => Dog says "Woof"

private / public

private変数・privateメソッドは変数名・メソッド名の前に__をつける

class Spam:
  __tax = 0.08
  value = 100

  # constructor
  def __init__(self, value = 100):
    self.value = value

  def __tax_amount(self, val):
    print( f'tax is {self.__tax}' )
    return int( round(val * self.__tax, 0) )

  def buy(self, num):
    amount = self.value * num
    return amount + self.__tax_amount(amount)

spam = Spam()
print( spam.buy(5) )
# => tax is 0.08
# => 540

spam.value = 300
print( spam.buy(5) )
# => tax is 0.08
# => 1620

# プライベート変数に外部からアクセス
print(spam.__tax)
# エラー
# AttributeError: 'Spam' object has no attribute '__tax'

# プライベートメソッドを外部から呼び出し
spam.__tax_amount(100)
# エラー
# AttributeError 'Spam' object has no attribute '__tax_amount'

# プライベート変数の置換え
#  => エラーにならないが無視される
spam.__tax = 0.1
print( spam.buy(5) )
# => tax is 0.08
# => 1620

プレイベート変数にアクセスしようとしたらエラーになったのですが、=で値を置き換えようとしたらエラーにならず無視されました。エラーにならないの理由がちょっと解りませんでした...

継承

クラス名に続けて()で継承元のクラスを指定する

class Ham:
  name = 'Ham'
  def say_name(self):
    print( self.name )

  def say(self):
    print('ham')

class Spam(Ham):
  def __init__(self):
    self.name = 'Spam'

  def say(self):
    self.say_name()

spam = Spam()
spam.say()
# => Spam
多重継承 (multiple inheritance)

継承乱発はあまり良くないと思うけど、多重継承もできるみたいなので試してみました。
継承元の指定を,区切りで多重継承ができるようです。

class A:
  def func(self):
    print('class A')

class B:
  def func(self):
    print('class B')

class C(B, A):
  pass

c = C()
c.func()
# => class B

多重継承した場合、メソッドが被っていると継承元として先に記述した方のメソッドが優先されるようです。


[参考]

スラスラ読める Pythonふりがなプログラミング (ふりがなプログラミングシリーズ)

スラスラ読める Pythonふりがなプログラミング (ふりがなプログラミングシリーズ)

Python 後で使う用に空の変数だけ作っておきたい。(変数宣言だけしたい)

なんとなくPythonJavaScriptに似てる気がしてきてる今日このごろ。

後のループとかで使うために関数の先頭とかで空の変数だけ作っておきたい(関数宣言だけしたい)ってのに少しハマったのでメモ。

varみたいな宣言文がPythonには無いので、変数だけ作ってみたらエラーになりました。

my_var
# => NameError: name 'my_var' is not defined

Pythonの変数は代入しないと作成されない。

Pythonの変数は型もなく、値を設定(代入)することで変数が作成されるという仕組みなようです。
つまり、何かしら代入しないと、その変数を探して「そんな名前の変数はない」とエラーを出すってことみたいです。

何かしら値を与えればOK

my_var = None

JavaScriptの変数巻き上げの癖で関数とかの先頭で変数定義したくなるので、同じような書き方しててハマってしましました。 先に使われる変数がある方が個人的には見通しが良いように感じるのですが、空文字''ではなく、Noneで変数を作成してもメモリ効率とかの面では良くないのでしょうか?
まぁ見通しが悪くなるくらい大きな関数作るなって話ですよね。。。


[参考]

変数人間 (ハヤカワ文庫SF)

変数人間 (ハヤカワ文庫SF)