파이썬에서 개인 모듈 함수 정의하기


238

http://www.faqs.org/docs/diveintopython/fileinfo_private.html 에 따르면 :

대부분의 언어와 마찬가지로 Python에는 개인 요소라는 개념이 있습니다.

  • 모듈 외부 에서 호출 할 수없는 개인 함수

그러나 두 파일을 정의하면

#a.py
__num=1

과:

#b.py
import a
print a.__num

내가 실행할 때 예외없이 b.py인쇄합니다 1. diveintopython이 잘못 되었습니까, 아니면 내가 잘못 이해 했습니까? 그리고 몇 가지 방법이 않는 비공개로 모듈의 함수를 정의는?


diveintopython이 틀린 것은 아니지만 예제에서는 >>> import fileinfo >>> m = fileinfo.MP3FileInfo() >>> m.__parse("/music/_singles/kairo.mp3") 1 Traceback (innermost last): File "<interactive input>", line 1, in ? AttributeError: 'MP3FileInfo' instance has no attribute '__parse' fileinfo.MP3FileInfo ()가 클래스의 인스턴스입니다. 이중 밑줄을 사용할 때이 예외가 발생합니다. 귀하의 경우 클래스를 만들지 않고 방금 모듈을 만들었습니다. 또한보십시오 : stackoverflow.com/questions/70528/…
Homero Esmeraldo

답변:


323

파이썬에서 "개인 정보 보호"는 "성인 협의"동의 수준에 달려 있습니다. 실제 생활에서 할 수있는 것보다 더 강요 할 수는 없습니다 . 당신이하지 않는 하나의 주요 밑줄 수단 가정 을 "외부에서"액세스 - 두 개의 선도 밑줄 (w / O를 후행 밑줄) 더욱 강력하게 메시지를 전달하지만, 결국, 그것은 여전히 사회에 따라 달라집니다 컨벤션 및 컨센서스 : 파이썬의 내성 (introspection)은 여러분이 바라는 바를 존중하기 위해 세계의 다른 모든 프로그래머를 수갑으로 만들 수 없을만큼 강력 합니다.

((비밀하게 비밀로 유지되지만 C ++에서도 거의 동일하게 유지됩니다. 대부분의 컴파일러의 경우 파일을 #define private public넣기 전에 간단한 줄만 #include있으면 .h현명한 코더가 "개인 정보"를 해시하는 데 필요한 모든 것입니다 ...!-) )


82
C ++에 대한 메모가 잘못되었습니다. #define private public을 사용하면 컴파일러로 전송되는 코드 (이름 변경이 발생하는 위치)가 변경됩니다.
rhinoinrepose

14
또한 C ++ 맹 글링은 모호하지만 거의 비밀이 아닙니다. C ++에 의해 생성 된 바이너리도 "내관"할 수 있습니다. OT, 미안
교수 Falken

47
@rhinoinrepose에 대한 업데이트는 잘못된 것이 아니라 전 처리기 매크로로 키워드를 재정의하는 표준에 따라 정의되지 않은 동작 입니다.
Cory Kramer

3
@AlexMartelli static void foo()그것이 얻는 것만 큼 사적인 것이 아닙니다 . 적어도 링커에 숨겨져 있으며 인라인으로 기능을 완전히 제거 할 수 있습니다.
user877329

3
현실에서 사람들은 법을 어기면 기소됩니다
Lay González

288

사이에 혼란이있을 수 있습니다 클래스 음부모듈 음부는 .

모듈 비공개 로 시작 밑줄 하나의
이러한 요소는 사용시 따라 복사되지 from <module_name> import *IMPORT 명령의 형태; 그러나 import <moudule_name>구문을 사용하면 가져옵니다 ( Ben Wilhelm의 답변 참조 )
질문 예제의 a .__ num에서 밑줄 하나를 제거하면 from a import *구문을 사용하여 a.py를 가져 오는 모듈에 표시되지 않습니다 .

클래스 개인 과 시작 두 개의 밑줄 (일명 던더 즉, D-ouble에서 점수)
이러한 변수는 클래스 명 등을 포함하는 "엉망"그 이름이
그것은 여전히 엉망이 이름을 통해 클래스 로직의 외부에서 액세스 할 수 있습니다.
이름 맹 글링은 무단 액세스에 대한 가벼운 예방 장치 역할을 할 수 있지만, 주요 목적은 조상 클래스의 클래스 구성원과 이름 충돌을 방지하는 것입니다. Alex Martelli의 재미 있고 정확한 성인 참고 자료를 참조 하십시오. 이러한 변수와 관련하여 사용 된 규칙을 설명합니다.

>>> class Foo(object):
...    __bar = 99
...    def PrintBar(self):
...        print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar  #direct attempt no go
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar()  # the class itself of course can access it
99
>>> dir(Foo)    # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar  #and get to it by its mangled name !  (but I shouldn't!!!)
99
>>>

TIL. __private_function그래도 모듈 수준을 시행하지 않는 이유는 무엇 입니까? 이 문제가 발생하여 오류가 발생했습니다.
Santa

@ Terrabits라는 친절한 단어에 감사드립니다.하지만 나는 'Python'의 모든 것에서 Alex (잘 뒤에!)에게 기뻐합니다. 또한 그의 대답은 Alex가 언어와 커뮤니티에 광범위한 기여를했을 때 높은 수준의 권위를 유지하면서 더 간결하고 유머러스합니다.
mjv

1
@mjv 이것은 매우 유용한 설명이었습니다! 감사합니다! 나는이 동작에 대해 오랫동안 당황했습니다. 클래스 private에 직접 액세스하려고하면 AttributeError 이외의 오류가 발생하도록 선택하십시오. 아마도 "PrivateAccessError"또는 무언가가 더 명백하거나 도움이되었을 것입니다. (속성이없는 오류가 발생하는 것은 실제로 사실 이 아닙니다 ).
HFBrowning

82

이 질문은 모듈 프라이버시가 순전히 일반적인 것이 아니므로 가져 오기 를 사용하면 사용 방법에 따라 모듈 프라이버시를 인식하거나 인식하지 못할 수 있으므로 완전히 대답 하지 못했습니다.

모듈에서 개인 이름을 정의하면 해당 이름 'import module_name'구문을 사용하는 스크립트로 가져옵니다. 따라서 예제에서 개인 모듈 _num을 a.py와 같이 올바르게 정의했다고 가정합니다.

#a.py
_num=1

.. 모듈 이름 기호로 b.py에서 액세스 할 수 있습니다.

#b.py
import a
...
foo = a._num # 1

a.py에서 비 개인 사용자 만 가져 오려면 from 구문을 사용해야 합니다.

#b.py
from a import *
...
foo = _num # throws NameError: name '_num' is not defined

그러나 명확성을 기하기 위해 모듈에서 이름을 가져올 때는 '*'로 모두 가져 오는 것이 아니라 이름을 가져올 때 명시 적으로하는 것이 좋습니다.

#b.py
from a import name1 
from a import name2
...

1
가져올 함수 / 라이브러리는 어디에서 지정합니까? 에서 초기화 평?
FistOfFury

_names호출 할 때 이름 충돌의 위험이 없습니다 .이 스타일을 사용할 때 import a와 같이 액세스 a._names할 수 있습니다.
Josiah Yoder

@FistOfFury 예, __init__.py파일로 가져온 함수를 지정 합니다. 이에 대한 도움이 필요하면 여기 를 참조 하십시오 .
Mike Williamson

29

파이썬은 이중 밑줄 로 개인 클래스 멤버를 허용 합니다. 이 기술은 모듈 수준에서 작동하지 않으므로 Dive Into Python에서는 실수라고 생각합니다.

개인 클래스 함수의 예는 다음과 같습니다.

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails

2
OP의 의도는 상용 패키지 외부에서 액세스 할 수없는 기능을 작성하는 것입니다. 이와 관련하여이 답변은 완전하지 않습니다. __bar () 함수는 여전히 f._foo__bar ()를 통해 외부에서 액세스 할 수 있습니다. 따라서 이중 밑줄은 개인용으로 만들지 않습니다.
SevakPrime 12

24

내부 기능을 추가 할 수 있습니다.

def public(self, args):
   def private(self.root, data):
       if (self.root != None):
          pass #do something with data

그런 수준의 개인 정보 보호가 정말로 필요한 경우에는 그런 것이 있습니다.


9
이것이 최선의 대답이 아닌 이유는 무엇입니까?
safay


1

클로저 또는 함수가 포함 된 방법이 있습니다. 이것은 브라우저 이외의 플랫폼이나 브라우저 워커에는 필요하지 않지만 JS에서 일반적입니다.

파이썬에서는 조금 이상해 보이지만 실제로 숨겨야 할 것이 있다면 그 방법이 될 수 있습니다. 파이썬 API를 사용하고 C (또는 다른 언어)로 숨겨야하는 것을 유지하는 것이 가장 좋은 방법 일 것입니다. 함수에 코드를 넣고 호출하고 내보내려는 항목을 반환하도록하지 않을 것입니다.


-11

파이썬은 개인, 공개 및 보호의 세 가지 모드를 가지고 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.