これの何が問題になっていますか?客観的および機能的な観点から?
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でカプセル化を実現するより良い方法はありますか?
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
としてアクセスできます。
まあ、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を使用できます。さらに、ダニエルのコメントは、リストの引数の制限を指摘しています。プライベートリストに「プライベート」と「保護」を追加することで、保護された「取得/設定」動作を維持できます。
したがって、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()
`