Program Club

파이썬에서 내장 함수 property ()를 사용하는시기와 방법

proclub 2020. 11. 6. 20:57
반응형

파이썬에서 내장 함수 property ()를 사용하는시기와 방법


약간의 구문 적 설탕을 제외하고는 property ()는 아무 소용이 없습니다.

물론, 그것의 좋은는 쓸 수 있도록 a.b=2대신 a.setB(2)하지만, 예기치 않은 결과가 같은 발생할 수 있습니다 때문에 AB = 2, 문제에 대한 조리법 같은 간단한 할당 외모가 아니라는 사실을 숨기고 a.b=2실제로는 원인이 a.b될을 1. 또는 예외가 발생합니다. 또는 성능 문제. 아니면 그냥 혼란 스러워요.

좋은 사용법에 대한 구체적인 예를 들어 주시겠습니까? (문제가있는 코드를 패치하는 데 사용하는 것은 계산되지 않습니다 ;-)


getter 및 setter에 의존하는 언어에서 자바처럼, 그들은 가정이나 아무것도 할 것으로 예상하지만,하지 않는 그들이 말하는 - 경우가 놀라운 것이 x.getB()아무것도했지만 논리적 속성의 현재 값을 반환 b하거나, 경우 x.setB(2)아무것도했지만 어떤 내부 작업의 소량하기 위해 필요한 x.getB()반환 2.

그러나이 예상되는 동작에 대해 언어가 부과하는 보증 은 없습니다 . 즉, 이름이 getor로 시작하는 메서드 본문에 대한 컴파일러 강제 제약 조건은 set상식, 사회적 관습, "스타일 가이드"및 테스트에 달려 있습니다. .

속성이있는 언어 (Python을 포함하지만 이에 국한되지 않는 언어 집합)에서 x.b와 같은 액세스 및 할당 동작은 Java와 같은 getter 및 setter 메서드와 정확히 동일합니다. 동일한 기대치, 언어로 인한 보장도 마찬가지입니다.x.b = 2

속성의 첫 번째 승리는 구문과 가독성입니다. 예를 들어, 작성해야

x.setB(x.getB() + 1)

명백한 대신

x.b += 1

신들에게 복수를 요구합니다. 속성을 지원하는 언어에서는 클래스의 사용자가 그러한 비잔틴 보일러 플레이트의 회전을 거치도록 강요하여 코드의 가독성에 영향을 미칠만한 이유가 전혀 없습니다.

특히 Python에서는 getter 및 setter 대신 속성 (또는 다른 설명자)을 사용하는 것보다 큰 장점이 하나 더 있습니다. 기본 setter 및 getter가 더 이상 필요하지 않도록 클래스를 다시 구성하면 클래스의 게시 된 API) 단순히 이러한 메서드와 그에 의존하는 속성을 제거 하여 '논리적'클래스 b의 일반적인 "저장된"속성을 x계산적으로 얻고 설정하는 속성을 만듭니다.

Python에서 메서드를 통해 (가능할 때) 직접 작업을 수행하는 것은 중요한 최적화이며, 체계적으로 속성을 사용하면 가능할 때마다이 최적화를 수행 할 수 있습니다 (항상 "일반적으로 저장된 속성"을 직접 노출하고 액세스시 계산이 필요한 속성 만 노출 및 / 또는 방법 및 속성을 통한 설정).

그래서, 당신은 사용자의 코드의 가독성에 영향을 넘어 getter 및 setter 대신 속성을 사용하는 경우, 당신은있다 또한 무상 기계 사이클 (그리고, 그주기 ;-) 동안 자신의 컴퓨터에가는 에너지 낭비 다시 없는 좋은 이유를 들어 도대체 무엇이.

속성에 대한 유일한 주장은 "외부 사용자는 일반적으로 할당의 결과로 어떤 부작용도 기대하지 않을 것"입니다. 그러나 동일한 사용자 (게터와 세터가 널리 퍼져있는 Java와 같은 언어에서)가 setter를 호출 한 결과로 "부작용"을 기대하지 않는다는 사실을 놓치게됩니다. ;-). 그것들은 합리적인 기대이며 클래스 작성자로서이를 수용하는 것은 여러분의 몫입니다. setter와 getter가 직접 사용 되든 속성을 통해 사용 되든 상관없이 차이가 없습니다. 당신이 중요한 관찰 부작용 방법이 있으면 할 수 없습니다 그 이름 getThis, setThat및 속성을 통해 그들을 사용하지 마십시오.

특성이 "구현을 숨기기"고 불만은 전적으로 부당하다 : 대부분의 모든 OOP의 정보 은폐를 구현하는 방법에 대한 것입니다 - 외부 세계에 논리적 인터페이스을 제시하고 할 수있는 최선으로 내부적으로 구현하기위한 클래스가 책임을 만들기. 속성과 똑같은 게터와 세터는이 목표를위한 도구입니다. 속성은 더 나은 작업을 수행합니다 (지원하는 언어에서 ;-).


아이디어는 실제로 필요할 때까지 getter와 setter를 작성하지 않아도되도록하는 것입니다.

따라서 시작하려면 다음과 같이 작성하십시오.

class MyClass(object):
    def __init__(self):
        self.myval = 4

분명히 이제 myobj.myval = 5.

그러나 나중에 동시에 영리한 작업을 수행하기 위해 세터가 필요하다고 결정합니다. 그러나 클래스를 사용하는 모든 코드를 변경할 필요는 없습니다. 따라서 @property데코레이터 에서 setter를 래핑하면 모두 작동합니다.


하지만 ab = 2가 단순한 할당이 아니라는 사실을 숨기는 것은 문제의 레시피처럼 보입니다

하지만 당신은 그 사실을 숨기지 않습니다. 그 사실은 시작되지 않았습니다. 이것은 python-고급 언어입니다. 조립이 아닙니다. 그 안에있는 "간단한"문장 중 일부는 단일 CPU 명령으로 귀결됩니다. 과제에 단순함을 읽는 것은 거기에없는 것을 읽는 것입니다.

xb = c라고 말할 때 아마도 "방금 무슨 일이 있어도 xb는 이제 c가되어야합니다"라고 생각해야합니다.


기본적인 이유는 단순히 더 좋아 보이기 때문입니다. 더 비단뱀 적입니다. 특히 도서관의 경우. something.getValue ()는 something.value보다 덜 멋져 보입니다.

plone (아주 큰 CMS)에서는 값 저장, 색인 생성 등 많은 작업을 수행하는 document.setTitle ()을 사용했습니다. document.title = 'something'하는 것이 더 좋습니다. 어쨌든 뒤에서 많은 일이 일어나고 있음을 알고 있습니다.


당신이 맞습니다, 그것은 단지 구문 론적 설탕입니다. 문제가있는 코드의 정의에 따라 좋은 용도가 없을 수도 있습니다.

애플리케이션에서 널리 사용되는 Foo 클래스가 있다고 가정하십시오. 이제이 응용 프로그램이 상당히 커졌고 더 나아가 매우 인기있는 웹 응용 프로그램이라고 가정 해 보겠습니다.

Foo가 병목 현상을 일으키고 있음을 식별합니다. 속도를 높이기 위해 Foo에 일부 캐싱을 추가 할 수 있습니다. 속성을 사용하면 Foo 외부에서 코드 나 테스트를 변경하지 않고도이를 수행 할 수 있습니다.

예 물론 이것은 문제가있는 코드이지만 신속하게 수정하여 많은 비용을 절약했습니다.

수백 또는 수천 명의 사용자가있는 라이브러리에 Foo가 있다면 어떨까요? Foo의 최신 버전으로 업그레이드 할 때 값 비싼 리팩터링을하도록 지시 할 필요가 없습니다.

릴리스 노트에는 단락 이식 가이드 대신 Foo에 대한 항목이 있습니다.

경험이 많은 Python 프로그래머는 a.b=2다른 사람에게 많은 것을 기대하지 않지만 a.b==2사실이 아닐 수도 있다는 것을 알고 있습니다. 수업 내에서 일어나는 일은 자신의 사업입니다.


여기 내 오래된 예가 있습니다. "void dt_setcharge (int atom_handle, int new_charge)"및 "int dt_getcharge (int atom_handle)"과 같은 기능이있는 C 라이브러리를 래핑했습니다. 나는 파이썬 수준에서 "atom.charge = atom.charge + 1"을하고 싶었습니다.

"property"데코레이터는이를 쉽게 만듭니다. 다음과 같은 것 :

class Atom(object):
    def __init__(self, handle):
        self.handle = handle
    def _get_charge(self):
        return dt_getcharge(self.handle)
    def _set_charge(self, charge):
        dt_setcharge(self.handle, charge)
    charge = property(_get_charge, _set_charge)

10 년 전,이 패키지를 작성할 때 __getattr__ 및 __setattr__을 사용해야했지만 구현은 훨씬 더 오류가 발생하기 쉽습니다.

class Atom:
    def __init__(self, handle):
        self.handle = handle
    def __getattr__(self, name):
        if name == "charge":
            return dt_getcharge(self.handle)
        raise AttributeError(name)
    def __setattr__(self, name, value):
        if name == "charge":
            dt_setcharge(self.handle, value)
        else:
            self.__dict__[name] = value

getters and setters are needed for many purposes, and are very useful because they are transparent to the code. Having object Something the property height, you assign a value as Something.height = 10, but if height has a getter and setter then at the time you do assign that value you can do many things in the procedures, like validating a min or max value, like triggering an event because the height changed, automatically setting other values in function of the new height value, all that may occur at the moment Something.height value was assigned. Remember, you don't need to call them in your code, they are auto executed at the moment you read or write the property value. In some way they are like event procedures, when the property X changes value and when the property X value is read.

참고URL : https://stackoverflow.com/questions/1554546/when-and-how-to-use-the-builtin-function-property-in-python

반응형