かもメモ

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

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ふりがなプログラミング (ふりがなプログラミングシリーズ)