파이썬의 '비공개'메소드가 실제로 비공개가 아닌 이유는 무엇입니까?
파이썬은 다음과 같이 이름에 이중 밑줄을 추가하여 클래스 내에서 '개인'메서드와 변수를 생성 할 수있는 기능을 제공합니다 __myPrivateMethod()
. 그렇다면 이것을 어떻게 설명 할 수 있습니까?
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
거래는 무엇입니까?!
잘 이해하지 못한 분들을 위해 조금 설명하겠습니다.
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
내가 한 일은 공개 메소드와 비공개 메소드로 클래스를 만들고 인스턴스화하는 것입니다.
다음으로 공개 메소드를 호출합니다.
>>> obj.myPublicMethod()
public method
다음으로 개인 메서드를 호출합니다.
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
여기에서는 모든 것이 좋아 보입니다. 우리는 그것을 부를 수 없습니다. 사실 '비공개'입니다. 글쎄, 실제로는 그렇지 않습니다. 객체에서 dir () 을 실행 하면 파이썬이 모든 '개인'메서드에 대해 마법처럼 만드는 새로운 마법의 메서드가 나타납니다.
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
This new method's name is always an underscore, followed by the class name, followed by the method name.
>>> obj._MyClass__myPrivateMethod()
this is private!!
So much for encapsulation, eh?
In any case, I'd always heard Python doesn't support encapsulation, so why even try? What gives?
The name scrambling is used to ensure that subclasses don't accidentally override the private methods and attributes of their superclasses. It's not designed to prevent deliberate access from outside.
For example:
>>> class Foo(object):
... def __init__(self):
... self.__baz = 42
... def foo(self):
... print self.__baz
...
>>> class Bar(Foo):
... def __init__(self):
... super(Bar, self).__init__()
... self.__baz = 21
... def bar(self):
... print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}
Of course, it breaks down if two different classes have the same name.
Example of private function
import re
import inspect
class MyClass :
def __init__(self) :
pass
def private_function ( self ) :
try :
function_call = inspect.stack()[1][4][0].strip()
# See if the function_call has "self." in the begining
matched = re.match( '^self\.', function_call )
if not matched :
print 'This is Private Function, Go Away'
return
except :
print 'This is Private Function, Go Away'
return
# This is the real Function, only accessible inside class #
print 'Hey, Welcome in to function'
def public_function ( self ) :
# i can call private function from inside the class
self.private_function()
### End ###
When I first came from Java to Python I hated this. It scared me to death.
Today it might just be the one thing I love most about Python.
I love being on a platform, where people trust each other and don't feel like they need to build impenetrable walls around their code. In strongly encapsulated languages, if an API has a bug, and you have figured out what goes wrong, you may still be unable to work around it because the needed method is private. In Python the attitude is: "sure". If you think you understand the situation, perhaps you have even read it, then all we can say is "good luck!".
Remember, encapsulation is not even weakly related to "security", or keeping the kids off the lawn. It is just another pattern that should be used to make a code base easier to understand.
From http://www.faqs.org/docs/diveintopython/fileinfo_private.html
Strictly speaking, private methods are accessible outside their class, just not easily accessible. Nothing in Python is truly private; internally, the names of private methods and attributes are mangled and unmangled on the fly to make them seem inaccessible by their given names. You can access the __parse method of the MP3FileInfo class by the name _MP3FileInfo__parse. Acknowledge that this is interesting, then promise to never, ever do it in real code. Private methods are private for a reason, but like many other things in Python, their privateness is ultimately a matter of convention, not force.
The phrase commonly used is "we're all consenting adults here". By prepending a single underscore (don't expose) or double underscore (hide), you're telling the user of your class that you intend the member to be 'private' in some way. However, you're trusting everyone else to behave responsibly and respect that, unless they have a compelling reason not to (e.g. debuggers, code completion).
If you truly must have something that is private, then you can implement it in an extension (e.g. in C for CPython). In most cases, however, you simply learn the Pythonic way of doing things.
It's not like you absolutly can't get around privateness of members in any language (pointer arithmetics in C++, Reflections in .NET/Java).
The point is that you get an error if you try to call the private method by accident. But if you want to shoot yourself in the foot, go ahead and do it.
Edit: You don't try to secure your stuff by OO-encapsulation, do you?
The class.__stuff
naming convention lets the programmer know he isn't meant to access __stuff
from outside. The name mangling makes it unlikely anyone will do it by accident.
True, you still can work around this, it's even easier than in other languages (which BTW also let you do this), but no Python programmer would do this if he cares about encapsulation.
Similar behavior exists when module attribute names begin with a single underscore (e.g. _foo).
Module attributes named as such will not be copied into an importing module when using the from*
method, e.g.:
from bar import *
However, this is a convention and not a language constraint. These are not private attributes; they can be referenced and manipulated by any importer. Some argue that because of this, Python can not implement true encapsulation.
It's just one of those language design choices. On some level they are justified. They make it so you need to go pretty far out of your way to try and call the method, and if you really need it that badly, you must have a pretty good reason!
Debugging hooks and testing come to mind as possible applications, used responsibly of course.
With Python 3.4 this is the behaviour:
>>> class Foo:
def __init__(self):
pass
def __privateMethod(self):
return 3
def invoke(self):
return self.__privateMethod()
>>> help(Foo)
Help on class Foo in module __main__:
class Foo(builtins.object)
| Methods defined here:
|
| __init__(self)
|
| invoke(self)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
>>> f = Foo()
>>> f.invoke()
3
>>> f.__privateMethod()
Traceback (most recent call last):
File "<pyshell#47>", line 1, in <module>
f.__privateMethod()
AttributeError: 'Foo' object has no attribute '__privateMethod'
https://docs.python.org/3/tutorial/classes.html#tut-private
Note that the mangling rules are designed mostly to avoid accidents; it still is possible to access or modify a variable that is considered private. This can even be useful in special circumstances, such as in the debugger.
Even if the question is old I hope my snippet could be helpful.
The most important concern about private methods and attributes is to tell developers not to call it outside the class and this is encapsulation. one may misunderstand security from encapsulation. when one deliberately uses syntax like that(bellow) you mentioned, you do not want encapsulation.
obj._MyClass__myPrivateMethod()
I have migrated from C# and at first it was weird for me too but after a while I came to the idea that only the way that Python code designers think about OOP is different.
Why are Python's 'private' methods not actually private?
As I understand it, they can't be private. How could privacy be enforced?
The obvious answer is "private members can only be accessed through self
", but that wouldn't work - self
is not special in Python, it is nothing more than a commonly-used name for the first parameter of a function.
참고URL : https://stackoverflow.com/questions/70528/why-are-pythons-private-methods-not-actually-private
'development' 카테고리의 다른 글
Git에서 파일을 이동 / 이름 변경하고 기록을 유지할 수 있습니까? (0) | 2020.10.02 |
---|---|
Node.js의 Connect, Express 및 "미들웨어"는 무엇입니까? (0) | 2020.10.02 |
MySQL 테이블, 인덱스 및 데이터 복제 (0) | 2020.10.02 |
'form'의 알려진 속성이 아니므로 'formGroup'에 바인딩 할 수 없습니다. (0) | 2020.10.02 |
일반적인 테스트 디렉터리 구조로 unittest 실행 (0) | 2020.10.02 |