web-dev-qa-db-ja.com

Pythonでカプセル化する方法は?

これの何が問題になっていますか?客観的および機能的な観点から?

import sys

class EncapsulationClass(object):

  def __init__(self):
    self.privates = ["__dict__", "privates", "protected", "a"]
    self.protected = ["b"]

    print self.privates

    self.a = 1
    self.b = 2
    self.c = 3
    pass

  def __getattribute__(self, name):
    if sys._getframe(1).f_code.co_argcount == 0:
      if name in self.privates:
        raise Exception("Access to private attribute \"%s\" is not allowed" % name)
      else:
        return object.__getattribute__(self, name)
    else:
      return object.__getattribute__(self, name)

  def __setattr__(self, name, value):
    if sys._getframe(1).f_code.co_argcount == 0:
      if name in self.privates:
        raise Exception("Setting private attribute \"%s\" is not allowed" % name)
      Elif name in self.protected:
        raise Exception("Setting protected attribute \"%s\" is not allowed" % name)
      else:
        return object.__setattr__(self, name, value)
    else:
      return object.__setattr__(self, name, value)


example = EncapsulationClass()

example.a = 10 # Exception: Setting private attribute "a" is not allowed
example.b = 10 # Exception: Setting protected attribute "b" is not allowed
example.c = 10 # example.c == 10

example.__dict__["privates"] # Exception: Setting protected attribute "b" is not allowed

このようなことをすることで実際に何が悪いのでしょうか?

Pythonでカプセル化を実現するより良い方法はありますか?

11
will

Pythonにはカプセル化があります-クラスで使用しています。

持っていないのは、プライベート属性や保護属性などのアクセス制御です。ただし、Pythonでは、属性に1つまたは2つのアンダースコアを前に付けることでプライベート属性を示す属性命名規則があります。例:

self._a
self.__a 

単一の下線は、属性がクラスにプライベートであると見なされるべきであり、直接アクセスされるべきではないことをクラスのユーザーに示します。

二重下線は同じことを示しますが、Python=は、属性名をいくらか壊して、隠そうとします。

class C(object):
    def __init__(self):
        self.a = 123    # OK to access directly
        self._a = 123   # should be considered private
        self.__a = 123  # considered private, name mangled

>>> c = C()
>>> c.a
123
>>> c._a
123
>>> c.__a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute '__a'
>>> c._C__a
123

最後の例では、名前が__aから_C__aに変更されていますが、クラス内ではself.__aとしてアクセスできます。

44
mhawke

まあ、Pythonには、アヒルのタイピングを頻繁に使用するのと同じように、一種の「哲学的」決定としてのカプセル化はありません。個人的には、プライベートまたは保護を使用する意味はわかりませんPythonコードの引数。

コードといえば、次のゲッターとセッターでうまく機能するようです。

def set_a(self, v):
    self.a = v

def get_a(self):
    return self.a

__ getattribute __(self、name)の最後の行に次の変更を加えた場合:

return object.__getattribute__(self, name)

ただし、mhawkeが述べたように、プライベート変数の前に__を付けると、変数保護の概念のようなcanを使用できます。さらに、ダニエルのコメントは、リストの引数の制限を指摘しています。プライベートリストに「プライベート」と「保護」を追加することで、保護された「取得/設定」動作を維持できます。

1

したがって、Python 3は、3レベルのデータアクセスを提供します。

1.public(public、特別な構文はありません、publicVariable)

2.保護(保護、名前の先頭に1つのアンダースコア、_protectedVariable);

3.private(private、名前の先頭に2つのアンダースコア、__ privateVariable)。

したがって、最後の1つはカプセル化と呼ばれます。つまり、オブジェクト(変数、メソッド)のコンポーネントへのアクセスを制限します。クラスの内部でメソッドを定義できるため、ユーザーは変数を表示したり、変数を変更したりできます。ユーザーにそのような特権を付与したい場合、プログラマーは、簡単に言えば、実際には、何が公開可能で何が内部的であるかを呼び出すようにプログラマーに与えます

プライベートとパブリックが基本であり、通常使用されます。ここに例があります

`

class phone:
    name="sony" #this variable is public
    __number= 201090943929 #this is private one ,and also my actual number heheheheeh boii
    def print_name(self): #this is public method
        print ('my phone name is:', self.name)
    def __print_number(self): #and private method
        print (self.__number)
#actually we(the programmer not the user)-while writing the code- can give the user the user the authority to only 
#see the value of the variable ,even to modify it by defining a metod inside the class 
    def print_private_number(self):
        return self.__number
    def modify_private_number(self,newNumber):
        self.__number=newNumber
        print(newNumber)
#now u can both prnt and modify the mumber with only the following methods

my_phone=phone()
my_phone.print_name() #now i called the public function , and cam simply print it as it's public (can be accessed)
print (my_phone.name) #same as here with variable
#Now if we tried to retrive private data ,or run private method
#its gonna end up with an error 
#print (my_phone.__number)
#my_phone.__print_number()

print (my_phone.print_private_number())
my_phone.modify_private_number(5)
#so what if the programmer didnt allow us to see the number 
#is that the end of the road ? nah ,we still can crack the system and both read and modify the private variables n functions
#hmmm am not gonna call it crack coz the langauage itself provides the programmer with 
#syntatic tool that circumvent encapsulation
print (my_phone._phone__number) 
#my_phone._phone__print_name() 

`

0
nemo07