試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

Pythonにおけるクラスのメンバを非公開にする

Pythonにおけるクラスのメンバは基本的に外部から直接参照可能(公開されている状態)となっているが、先頭にアンダースコア(「_」の文字)が2つ付いた名前のメンバは内部的に別の名前に変更され(難号化/mangle)、外部からの参照を禁止することができる。これにより、プログラムをより信頼できるものにできる。ただし、仕様として完全にアクセスを禁止するものではない。*1
下はテストで、クラスTestClassのメンバ「__c」「__d」「__get_d()」がクラス内で参照可能なのに対して、外部から直接参照しようとしても失敗する。

#! /usr/bin/python
# -*- encoding: utf-8 -*-

class TestClass:
  """
  テストクラス
  """
  a = 1
  __d = 4  # 外部からアクセスできない
  def __init__(self):
    self.b = 2
    self.__c = 3  # 外部からアクセスできない
  def get_c(self):
    return self.__c
  def get_d(self):
    return self.__d
  def __get_d(self):  # 外部からアクセスできない
    return self.__d

obj = TestClass()
# 1
print 'obj.a: %d' % obj.a
# 2
print 'obj.b: %d' % obj.b
# 3
print 'obj.get_c(): %d' % obj.get_c()
# 4
print 'obj.get_d(): %d' % obj.get_d()
# AttributeError: TestClass instance has no attribute '__c'
try:
  print 'obj.__c: %d' % obj.__c
except AttributeError, msg:
  print 'AttributeError: %s' % msg
# AttributeError: TestClass instance has no attribute '__d'
try:
  print 'obj.__d: %d' % obj.__d
except AttributeError, msg:
  print 'AttributeError: %s' % msg
# AttributeError: TestClass instance has no attribute '__get_d'
try:
  print 'obj.__get_d(): %d' % obj.__get_d()
except AttributeError, msg:
  print 'AttributeError: %s' % msg

下は実行結果。

obj.a: 1
obj.b: 2
obj.get_c(): 3
obj.get_d(): 4
AttributeError: TestClass instance has no attribute '__c'
AttributeError: TestClass instance has no attribute '__d'
AttributeError: TestClass instance has no attribute '__get_d'

参考URL:

*1:チュートリアルでも「難号化は主に不慮の事故を防ぐため」と書かれている