문제

Python에서 메서드와 데이터 멤버를 비공개로 만들려면 어떻게 해야 하나요?아니면 Python이 개인 멤버를 지원하지 않습니까?

도움이 되었습니까?

해결책

9.6. 개인 변수

객체 내부를 제외하고 액세스 할 수없는 "개인"인스턴스 변수는 파이썬에는 존재하지 않습니다. 그러나 대부분의 Python 코드가 뒤 따르는 규칙이 있습니다. 밑줄 (예 : _spam)이있는 이름은 API의 비공개 부분으로 취급되어야합니다 (함수, 방법 또는 데이터 구성원). . 구현 세부 사항으로 간주되고 통지없이 변경 될 수 있습니다.

클래스-민간 회원에 대한 유효한 사용 사례가 있기 때문에 (즉, 서브 클래스로 정의 된 이름의 이름 충돌을 피하기 위해), 이름 Mangling이라는 이러한 메커니즘에 대한 지원이 제한되어 있습니다. __spam 양식의 식별자 (최소 2 개의 주요 밑줄, 최대 하나의 후행 밑줄)가 텍스트로 대체됩니다. _classname__spam, 여기서 클래스 이름은 선행 밑줄이 벗겨진 현재 클래스 이름입니다. 이 망설은 클래스의 정의 내에서 발생하는 한 식별자의 구문 위치와 상관없이 수행됩니다.

그래서, 예를 들어,

class Test:
    def __private_symbol(self):
        pass
    def normal_symbol(self):
        pass

print dir(Test)

출력 :

['_Test__private_symbol', 
'__doc__', 
'__module__', 
'normal_symbol']

__private_symbol 개인 방법으로 간주되어야하지만 여전히 액세스 할 수 있습니다. _Test__private_symbol.

다른 팁

다른 답변은 기술적 인 세부 사항을 제공합니다. 한편으로는 Python과 C ++/Java와 같은 언어의 철학의 차이를 강조하고 싶습니다 (질문에 따라 익숙하다고 생각합니다).

Python의 일반적인 태도 (및 해당 문제에 대한 Perl)는 속성의 '개인 정보'가 컴파일러/통역사의 철조망 울타리 대신 프로그래머에게 요청하는 것입니다. 아이디어는 잘 요약되어 있습니다 이 메일 그리고 프로그래머가 내부와 교배하지 않을 정도로 책임이 있다고 가정하기 때문에 종종 "우리는 모두 동의하는 성인"이라고합니다. 선행 밑줄은 속성이 내부임을 말하는 정중 한 메시지 역할을합니다.

반면에, 당신이 있다면 하다 일부 응용 프로그램의 내부에 액세스하고 싶을 때 (주목할만한 예는 PYDOC와 같은 문서 생성기) 자유롭게 할 수 있습니다. Onus는 당신이하고있는 일을 아는 것을 알 수있는 프로그래머로서 당신에게 있습니다. 이것의 방법.

아니요 private 파이썬의 다른 액세스 보호 메커니즘 중. 문서화 된 협약이 있습니다 파이썬 스타일 가이드 귀하의 클래스 사용자에게 특정 속성에 액세스하지 않아야한다는 것을 나타냅니다.

  • _single_leading_underscore : 약한 "내부 사용"표시기. 예를 들어 from M import * 이름이 밑줄로 시작하는 오브젝트를 가져 오지 않습니다.

  • Single_trailing_underscore_ : Python 키워드와의 충돌을 피하기 위해 컨벤션에서 사용 Tkinter.Toplevel(master, class_='ClassName')

  • __double_Leading_underscore : 클래스 속성 이름을 지정할 때 이름 Mangling을 호출합니다 (Class foobar, __boo는 _foobar__boo, 아래 참조).

파이썬 함수, 클래스 메소드 또는 속성의 이름이 두 밑줄로 시작하지만 끝나지 않는 경우 개인입니다. 다른 모든 것은 공개적입니다. Python은 보호 된 클래스 방법에 대한 개념이 없습니다 (자체 클래스 및 후손 수업에서만 액세스 할 수 있음). 클래스 방법은 비공개 (자신의 클래스에서만 액세스 가능) 또는 공개 (어디서나 액세스 할 수 있음)입니다.

파이썬으로 뛰어 들었습니다

Python은 개인정보 보호를 직접적으로 지원하지 않습니다.프로그래머는 언제 외부에서 속성을 수정하는 것이 안전한지 알아야 하지만 어쨌든 Python을 사용하면 약간의 트릭으로 비공개와 같은 것을 달성할 수 있습니다.이제 개인이 비공개로 무엇이든 넣을 수 있는지 여부를 살펴보겠습니다.

class Person(object):

    def __priva(self):
        print "I am Private"

    def publ(self):
        print " I am public"

    def callpriva(self):
        self.__priva()

이제 실행 시점은 다음과 같습니다.

>>> p = Person()
>>> p.publ()
 I am public
>>> p.__priva()
Traceback (most recent call last):
  File "", line 1, in 
    p.__priva()
AttributeError: 'Person' object has no attribute '__priva'
​#Explanation   : You can see  here we are not able to fetch that private method directly.
>>> p.callpriva()
I am Private
#​Explanation  : Here we can access private method inside class​

​그럼 누군가가 해당 변수에 어떻게 접근할 수 있나요???
당신은 다음과 같이 할 수 있습니다 :

>>>p._Person__priva
I am Private

​와우, 실제로 파이썬이 이중 밑줄로 시작하는 변수를 가져오는 경우 단일 밑줄과 클래스 이름을 시작 부분에 추가하여 "번역"됩니다.

메모 : 이 이름을 변경하고 싶지 않지만 다른 개체가 멀리 떨어져 있도록 신호를 보내고 싶다면 별표가 표시된 가져오기(모듈 가져오기 *에서)로 가져오지 않는 초기 밑줄이 있는 단일 초기 밑줄 이름을 사용할 수 있습니다.
예 :

#test.py
def hello():
    print "hello"
def _hello():
    print "Hello private"

#----------------------
#test2.py
from test import *
print hello()
print _hello()

출력-->

hello
Traceback (most recent call last):
  File "", line 1, in 
NameError: name '_hello' is not defined

이제 _hello를 수동으로 호출해 보겠습니다.

#test2.py
from test import _hello , hello
print hello()
print _hello()

출력-->

hello
hello private

마지막으로 :Python은 실제로 동등한 개인 정보 지원을 가지고 있지 않지만 단일 및 이중 초기 밑줄은 어느 정도까지 두 가지 수준의 개인 정보를 제공합니다.

이것은 작동 할 수 있습니다 :

import sys, functools

def private(member):
    @functools.wraps(member)
    def wrapper(*function_args):
      myself = member.__name__
      caller = sys._getframe(1).f_code.co_name
      if (not caller in dir(function_args[0]) and not caller is myself):
         raise Exception("%s called by %s is private"%(myself,caller))
      return member(*function_args)
    return wrapper

class test:
   def public_method(self):
      print('public method called')

   @private
   def private_method(self):
      print('private method called')

t = test()
t.public_method()
t.private_method()

이것은 긴 대답이지만, 여기서 실제 문제의 근본 원인 인 가시성의 범위에 도달한다고 생각합니다. 내가 이것을 밟는 동안 그냥 거기에 매달려!

단순히 모듈을 가져 오면 응용 프로그램 개발자가 모든 클래스 또는 방법에 액세스 할 필요는 없습니다. 실제로 모듈 소스 코드를 볼 수 없다면 사용 가능한 내용을 어떻게 알 수 있습니까? 어떤 사람 (또는 어떤 것)는 내가 할 수있는 일을 말하고 내가 사용할 수있는 기능을 사용하는 방법을 설명해야합니다. 그렇지 않으면 모든 것이 나에게 쓸모가 없습니다.

가져 오기 모듈을 통한 기본 클래스 및 방법을 기반으로 높은 수준의 추상화를 개발하는 사람들에게는 실제 소스 코드가 아닌 사양 문서가 제공됩니다.

모듈 사양은 클라이언트 개발자에게 표시되는 모든 기능을 설명합니다. 대규모 프로젝트 및 소프트웨어 프로젝트 팀을 처리 할 때는 모듈의 실제 구현은 항상 사용하는 사람들과 숨겨져 있어야합니다. 외부 세계에 대한 인터페이스가있는 블랙 박스입니다. OOD 순수 주의자들에게, 나는 기술자 용어가 "분리"와 "일관성"이라고 생각합니다. 모듈 사용자는 구현 세부 사항에 부담없이 인터페이스 메소드 만 알아야합니다.

기본 사양 문서를 먼저 변경하지 않고 모듈을 변경해서는 안되며, 코드를 변경하기 전에 일부 조직에서 검토 / 승인이 필요할 수 있습니다.

Hobby 프로그래머 (현재 은퇴)로서 SPEC Doc이 실제로 모듈 상단에 거대한 주석 블록으로 작성된 새 모듈을 시작하면 사용자가 실제로 SPEC 라이브러리에서 볼 수있는 부분이됩니다. 그것은 단지 나이기 때문에, 나는 아직 도서관을 설정하지 않았지만 쉽게 할 수있을 것입니다.

그런 다음 다양한 클래스와 메소드를 작성하여 코딩을 시작하지만 기능 본문이없는 "print ()"와 같은 null print 문만으로 모듈이 구문 오류없이 컴파일 할 수있을만큼 충분합니다. 이 단계가 완료되면 완성 된 null 모듈을 컴파일합니다. 이것이 내 사양입니다. 프로젝트 팀에서 일하고 있다면 신체를 살펴보기 전에 검토 및 해설을 위해이 사양/인터페이스를 발표 할 것입니다.

각 방법의 신체를 한 번에 하나씩 살펴보고 그에 따라 컴파일하여 구문 오류가 즉시 즉시 수정되도록합니다. 또한 하단에 임시 "메인"실행 섹션을 작성하여 각 방법을 코딩 할 때 각 방법을 테스트하기에 좋은시기입니다. 코딩/테스트가 완료되면 모든 테스트 코드가 다시 필요할 때까지 댓글을 달아야합니다.

실제 개발 팀에서는 사양 코멘트 블록도 문서 제어 라이브러리에도 나타나지 만 또 다른 이야기입니다. 요점은 다음과 같습니다. 귀하는 모듈 클라이언트로서 소스 코드가 아닌이 사양 만 참조하십시오.

PS : 처음 시작하기 오래 전에, 나는 국방 항공 우주 공동체에서 일했고 우리는 꽤 멋진 일을했지만 독점적 인 알고리즘 및 민감한 시스템 제어 로직과 같은 것들은 슈퍼 듀퍼 보안 소프트웨어 라이브러리에서 단단히 아치형으로 암호화되어 암호화되었습니다. 모듈 / 패키지 인터페이스에 액세스 할 수 있었지만 Blackbox 구현 본문은 아닙니다. 모든 시스템 수준 디자인, 소프트웨어 사양, 소스 코드 및 테스트 레코드를 처리하는 문서 관리 도구가있었습니다. 모두 함께 동기화되었습니다. 정부는 엄격한 요구 사항 소프트웨어 품질 보증 표준을 가졌습니다. "Ada"라는 언어를 기억하십니까? 그게 내가 몇 살이야!

나는 Python 2.7과 3.5를 사용합니다. 나는이 코드를 썼다 :

class MyOBject(object):
    def __init__(self):
        self.__private_field = 10


my_object = MyOBject()
print(my_object.__private_field)

실행하고 얻었습니다.

AttributeError : 'myObject'객체는 속성이 없습니다 '__private_field'

참조하십시오 :https://www.tutorialsteacher.com/python/private-and-protected-access-modifiers-in-python

파이썬에서 메소드 또는 데이터 멤버를 비공개로 만들려면 __setattr __를 사용하십시오.

class Number:
    def __init__(self,value):
        self.my_private = value

    def __setattr__(self, my_private, value):
        # the default behavior
        # self.__dict__[my_private] = value
        raise Exception("can't access private member-my_private")


def main():
    n = Number(2)
    print(n.my_private)

if __name__ == '__main__': 
    main()
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top