source

@property와 getters 및 setter의 비교

lovecheck 2023. 1. 15. 17:01
반응형

@property와 getters 및 setter의 비교

의 장점은 입니까?@propertygetter+setter는요?프로그래머는 어떤 특정한 상황에서 하나를 다른 것 보다 사용해야 하는가?

속성 포함:

class MyClass(object):
    @property
    def my_attr(self):
        return self._my_attr

    @my_attr.setter
    def my_attr(self, value):
        self._my_attr = value

속성 없음:

class MyClass(object):
    def get_my_attr(self):
        return self._my_attr

    def set_my_attr(self, value):
        self._my_attr = value

속성을 선호합니다.그게 그들이 거기 있는 이유야.

그 이유는 Python에서는 모든 속성이 공개되어 있기 때문입니다.이름을 밑줄이나 두 개로 시작하는 것은 지정된 속성이 향후 버전의 코드에서는 동일하지 않을 수 있는 구현 세부 사항이라는 경고에 불과합니다.이 속성을 실제로 가져오거나 설정하는 데 방해가 되지 않습니다.따라서 표준 속성 액세스는 속성에 액세스하는 일반적인 피톤식 방법입니다.

속성의 장점은 속성 액세스와 구문적으로 동일하기 때문에 클라이언트 코드를 변경하지 않고 다른 속성으로 변경할 수 있다는 것입니다.속성을 사용하는 코드를 변경하지 않고 속성을 사용하는 버전(예: 계약별 코드 또는 디버깅용)과 프로덕션용 속성을 사용하지 않는 버전 하나를 가질 수도 있습니다.동시에 나중에 접근을 더 잘 제어해야 할 경우를 대비해 모든 것에 대해 getters와 setters를 작성할 필요는 없습니다.

Python에서는 재미로 getters, setters 또는 속성을 사용하지 않습니다.먼저 속성만 사용하고 나중에 필요한 경우에만 클래스를 사용하여 코드를 변경할 필요 없이 속성으로 마이그레이션합니다.

확장자가 .py인 코드에는 getters, setters, 상속 및 의미 없는 클래스가 많이 있습니다.예를 들어 간단한 태플이 가능한 모든 곳에서 사용할 수 있지만 Python을 사용하여 C++ 또는 Java로 작성한 코드입니다.

그건 파이썬 코드가 아니야

속성을 사용하면 일반 속성 액세스로 시작한 다음 나중에 필요에 따라 gettersetter로 백업할 수 있습니다.

간단히 말하면, 부동산은 쉽게 이길 수 있습니다.항상.

가끔 게터나 세터가 필요하지만, 그래도 저는 그것들을 외부에 '숨기고' 있습니다.Python, Python, Python, Python, Python, Python Python Python Python Python Python Python Python Python Python 방법이 있습니다.getattr,setattr,__getattribute__등입니다만, 매우 간결하고 알기 쉬운 것은, 다음과 같습니다.

def set_email(self, value):
    if '@' not in value:
        raise Exception("This doesn't look like an email address.")
    self._email = value

def get_email(self):
    return self._email

email = property(get_email, set_email)

다음은 Python의 getters와 setters에 대해 소개하는 간단한 기사입니다.

[TL;DR? 코드 예시는 끝까지 건너뛸있습니다]

저는 사실 다른 관용어를 사용하는 것을 선호합니다.그것은 일회성으로 사용하는 것에 조금 관여하고 있습니다만, 좀 더 복잡한 사용 사례가 있으면 좋겠습니다.

일단 배경부터.

속성은 프로그래밍 방식으로 설정 및 값 가져오기를 모두 처리할 수 있지만 속성으로 액세스할 수 있다는 점에서 유용합니다.「취득」을 「컴퓨터」(본질적으로)로 변환해, 「세트」를 「이벤트」로 변환할 수 있습니다.예를 들어 다음과 같은 클래스가 있다고 합시다.이 클래스는 Java와 같은 getter와 setter로 코드화되어 있습니다.

class Example(object):
    def __init__(self, x=None, y=None):
        self.x = x
        self.y = y

    def getX(self):
        return self.x or self.defaultX()

    def getY(self):
        return self.y or self.defaultY()

    def setX(self, x):
        self.x = x

    def setY(self, y):
        self.y = y

    def defaultX(self):
        return someDefaultComputationForX()

    def defaultY(self):
        return someDefaultComputationForY()

가 왜 않았을까 수도 요.defaultX ★★★★★★★★★★★★★★★★★」defaultY그 the the the __init__방법.그 이유는 우리 사건의 경우, 그 사건에서someDefaultComputation에서는, 「 스탬프」라고 및 「 스탬프」라고 하는 시간에 따라서 됩니다.x (오류)y되어 있지 에서는 「 set으로 되어 있는 것을 합니다). 「none」의 값이 합니다.x ( ( )y 계산s) ""

그래서 이것은 위에서 설명한 많은 이유로 재미없다.속성을 사용하여 다시 씁니다.

class Example(object):
    def __init__(self, x=None, y=None):
        self._x = x
        self._y = y

    @property
    def x(self):
        return self.x or self.defaultX()

    @x.setter
    def x(self, value):
        self._x = value

    @property
    def y(self):
        return self.y or self.defaultY()

    @y.setter
    def y(self, value):
        self._y = value

    # default{XY} as before.

우리가 얻은 게 뭐죠?이러한 속성을 속성으로 참조할 수 있게 되었습니다.이러한 속성에서는, 백그라운드에서 메서드를 실행할 수 있게 됩니다.

물론 속성의 진정한 힘은 일반적으로 이러한 방법이 단순히 값을 가져오고 설정하는 것 외에 다른 작업을 수행하기를 원한다는 것입니다(그렇지 않으면 속성을 사용하는 의미가 없습니다).나는 이것을 내 getter의 예에서 했다.기본적으로 값이 설정되지 않을 때마다 기본값을 선택하는 함수 본문을 실행하고 있습니다.이것은 매우 일반적인 패턴입니다.

하지만 우리는 무엇을 잃고 있고, 무엇을 할 수 없는가?

제 생각에 가장 골치 아픈 점은 (여기서와 같이) getter를 정의하면 setter도 정의해야 한다는 것입니다.[1] 코드를 혼란스럽게 하는 추가 노이즈입니다.

하나 점은 ''를 해야 입니다.x ★★★★★★★★★★★★★★★★★」y의 값__init__ (도 있죠.setattr()더 많은 추가 코드입니다.)

셋째, Java와 같은 예시와 달리 getters는 다른 파라미터를 받아들일 수 없습니다.이제 당신이 이미 말하는 것을 들을 수 있습니다. 만약 그것이 매개 변수를 취하는 것이라면, 그것은 게터가 아닙니다!공식적인 의미에서 그것은 사실이다.에서 우리는 속성을 . 예를 들어, 명명된 속성을 매개 변수화할 수 .x

다음과 같은 일을 할 수 있으면 좋겠습니다.

e.x[a,b,c] = 10
e.x[d,e,f] = 20

예를들면.가장 가까운 것은 할당을 덮어쓰고 몇 가지 특별한 의미를 내포하는 것입니다.

e.x = [a,b,c,10]
e.x = [d,e,f,30]

그리고 물론, 사전의 키로서 처음 3개의 값을 추출해, 그 값을 수치로 설정하는 방법을, 설정자가 알고 있는 것을 확인합니다.

그러나 이 기능을 사용하더라도 파라미터를 getter에 전혀 전달할 수 없기 때문에 값을 얻을 방법이 없기 때문에 속성으로 지원할 수 없습니다.그래서 우리는 비대칭성을 도입하면서 모든 것을 되돌려야 했습니다.

Java 스타일의 getter/setter를 통해 이 문제를 해결할 수 있지만 getter/setter가 필요합니다.

우리가 진정으로 원하는 것은 다음과 같은 요건을 충족시키는 것입니다.

  • 사용자는 특정 Atribut에 대해 하나의 메서드만 정의하고 Atribut이 읽기 전용인지 읽기/쓰기인지 지정할 수 있습니다.속성이 쓰기 가능한 경우 속성은 이 테스트에 실패합니다.

  • 가 되는 에, 「변수」는.__init__ ★★★★★★★★★★★★★★★★★」setattr암호에 입력되어 있습니다.변수는 우리가 이 새로운 스타일의 속성을 만들었다는 사실만으로 존재합니다.

  • Atribute의 디폴트코드는 메서드 본문 자체에서 실행됩니다.

  • Atribute로서 Atribute로서 설정해, Atribute로서 참조할 수 있습니다.

  • 속성을 파라미터화할 수 있습니다.

코드에 관해서는, 다음을 기술하는 방법을 원합니다.

def x(self, *args):
    return defaultX()

다음 작업을 수행할 수 있습니다.

print e.x     -> The default at time T0
e.x = 1
print e.x     -> 1
e.x = None
print e.x     -> The default at time T1

기타 등등.

파라미터화 가능한 Atribute의 특수한 케이스에 대해서도, 디폴트 할당 케이스가 기능하도록 하고 싶다고 생각하고 있습니다.내가 이 문제를 어떻게 해결했는지 아래를 보게 될 것이다.

자, 요점만 말씀해주세요.이에 대한 해결방안은 다음과 같습니다.

속성의 개념을 대체할 새 개체를 만듭니다.오브젝트는 변수 세트의 값을 저장하는 것을 목적으로 하며 기본값을 계산하는 방법을 알고 있는 코드에 대한 핸들도 유지합니다.입니다.value '을 실행합니다.method이 값이 설정되지 않은 경우.

을 '오빠'라고 부르자UberProperty.

class UberProperty(object):

    def __init__(self, method):
        self.method = method
        self.value = None
        self.isSet = False

    def setValue(self, value):
        self.value = value
        self.isSet = True

    def clearValue(self):
        self.value = None
        self.isSet = False

는 각 i i라고 생각한다.method은 수업 방법인 ' 방법입니다.value입니다.UberProperty는 , 을 했습니다.isSetNone실제 값이 될 수 있으며, 이를 통해 진정한 "가치 없음"을 선언할 수 있습니다.을 하다

이것은 기본적으로 우리가 원하는 것을 할 수 있는 객체를 제공하지만, 실제로 어떻게 그것을 우리 반에 배치할 수 있을까요?부동산은 장식가들을 이용하는데, 왜 우리는 못하죠?서는 ' '속성', '속성', '속성' 한 x를 참조해 주세요.

class Example(object):

    @uberProperty
    def x(self):
        return defaultX()

물론 이것은 아직 실제로 효과가 있는 것은 아닙니다.하지 안 된다uberProperty와 setsgets를 할 수 있는지 합니다.

gets부터 시작합시다.

첫 번째 시도는 단순히 새로운 UberProperty 객체를 생성하여 반환하는 것이었습니다.

def uberProperty(f):
    return UberProperty(f)

물론 저는 이것이 효과가 없다는 것을 금방 깨달았습니다.Python은 호출 가능한 것을 오브젝트에 바인드하지 않고 함수를 호출하기 위해 오브젝트가 필요합니다.교실에서 데코레이터를 만드는 것조차 효과가 없습니다. 지금은 수업이 있지만, 아직 함께 일할 대상이 없습니다.

그래서 우리는 여기서 더 많은 것을 할 수 있어야 합니다.은 한알 수 있기 UberPropertymethod★★★★

class UberProperty(object):

    def __init__(self, method):
        self.method = method

또, 호출할 수 없기 때문에, 현시점에서는 아무것도 동작하고 있지 않습니다.

그림을 어떻게 완성하죠?새로운 데코레이터를 사용하여 예제 클래스를 만들면 다음과 같은 결과가 초래됩니다.

class Example(object):

    @uberProperty
    def x(self):
        return defaultX()

print Example.x     <__main__.UberProperty object at 0x10e1fb8d0>
print Example().x   <__main__.UberProperty object at 0x10e1fb8d0>

, 「」는 됩니다.UberProperty물론 콜러블이 아니기 때문에 별로 쓸모가 없습니다.

한 것은 하는 방법입니다.UberProperty클래스를 클래스의 오브젝트로 만든 후 해당 오브젝트를 사용하기 위해 해당 사용자에게 반환하기 전에 데코레이터에 의해 생성된 인스턴스.__init__화해, 친친

을 사용법는 묶묶을 UberPropertyBound Uber Property 。할 수 x여하하다

class BoundUberProperty(object):
    def __init__(self, obj, uberProperty):
        self.obj = obj
        self.uberProperty = uberProperty
        self.isSet = False

    def setValue(self, value):
        self.value = value
        self.isSet = True

    def getValue(self):
        return self.value if self.isSet else self.uberProperty.method(self.obj)

    def clearValue(self):
        del self.value
        self.isSet = False

그럼 어떻게 하면 오브젝트에 올릴 수 있을까요?이 있지만 할 수 있는 은 '만을 사용하는 것입니다.__init__맵핑 방법을 지정합니다.__init__을 훑어보기만 하면 .__dict__이 Attribute "type" Attribute "type"인 Attribute "type"인를 업데이트합니다.UberProperty.

이제 uber-properties는 멋지고 많이 사용하고 싶기 때문에 모든 서브클래스에 대해 이 기능을 수행하는 기본 클래스를 만드는 것이 좋습니다.기본 클래스가 어떻게 불릴지 아실 겁니다.

class UberObject(object):
    def __init__(self):
        for k in dir(self):
            v = getattr(self, k)
            if isinstance(v, UberProperty):
                v = BoundUberProperty(self, v)
                setattr(self, k, v)

하고, 를 「」, 「」, 「」, 「」로부터 .UberObject및 ... ...

e = Example()
print e.x               -> <__main__.BoundUberProperty object at 0x104604c90>

" " " 후x 표시:

@uberProperty
def x(self):
    return *datetime.datetime.now()*

간단한 테스트를 실행할 수 있습니다.

print e.x.getValue()
print e.x.getValue()
e.x.setValue(datetime.date(2013, 5, 31))
print e.x.getValue()
e.x.clearValue()
print e.x.getValue()

그리고 우리가 원하는 결과를 얻을 수 있습니다.

2013-05-31 00:05:13.985813
2013-05-31 00:05:13.986290
2013-05-31
2013-05-31 00:05:13.986310

(저, 늦게까지 일해요.)

「 」를 .getValue,setValue , , , , 입니다.clearValue제가 아직 이걸 자동으로 돌려받을 수 있는 방법을 찾지 못했기 때문입니다.

하지만 지금은 여기서 멈추는 게 좋을 것 같아요. 피곤해서요.또, 필요한 핵심 기능이 갖추어져 있는 것을 알 수 있습니다.나머지 기능은 윈도 드레싱입니다.중요한 조작성 윈도 드레싱입니다만, 투고를 갱신할 때까지 기다릴 수 있습니다.

다음 투고에서는 다음 사항에 대해 설명하면서 예를 마치겠습니다.

  • UberObject를 .__init__는 항상 서브클래스에 의해 호출됩니다.

    • 그래서 강제로 어디론가 부르거나, 아니면 실행이 되지 않도록 해야 합니다.
    • 메타클래스로 하는 방법을 알아보겠습니다.
  • 다음과 같은 기능을 다른 것으로 '에일리어스'하는 일반적인 사례를 반드시 처리해야 합니다.

      class Example(object):
          @uberProperty
          def x(self):
              ...
    
          y = x
    
  • 는 필요하다e.xe.x.getValue()폴트입입니니다

    • 여기서 실제로 볼 수 있는 것은 모델이 실패하는 한 가지 영역입니다.
    • 가치를 얻기 위해서는 항상 함수 호출을 사용해야 합니다.
    • , 할 수 에, 「 」, 「 」를 사용하지 않아도 됩니다.e.x.getValue()(아직 수정하지 않았다면 이 작업을 수행하는 것이 당연합니다.)
  • 세팅에 합니다.e.x directly 」와 e.x = <newvalue> 수 , 이 부분은 __init__코드를 사용할 수 있습니다.

  • 마지막으로 파라미터화된 속성을 추가합니다.우리가 이걸 어떻게 할지는 분명할 거야.

다음은 지금까지의 코드입니다.

import datetime

class UberObject(object):
    def uberSetter(self, value):
        print 'setting'

    def uberGetter(self):
        return self

    def __init__(self):
        for k in dir(self):
            v = getattr(self, k)
            if isinstance(v, UberProperty):
                v = BoundUberProperty(self, v)
                setattr(self, k, v)


class UberProperty(object):
    def __init__(self, method):
        self.method = method

class BoundUberProperty(object):
    def __init__(self, obj, uberProperty):
        self.obj = obj
        self.uberProperty = uberProperty
        self.isSet = False

    def setValue(self, value):
        self.value = value
        self.isSet = True

    def getValue(self):
        return self.value if self.isSet else self.uberProperty.method(self.obj)

    def clearValue(self):
        del self.value
        self.isSet = False

    def uberProperty(f):
        return UberProperty(f)

class Example(UberObject):

    @uberProperty
    def x(self):
        return datetime.datetime.now()

[1] 아직 이 상황인지 아닌지에 대해서는 늦어질 수 있습니다.

둘 다 각자의 자리가 있는 것 같아요." " " 를 사용하는 의 문제 중 @property표준 클래스 메커니즘을 사용하여 하위 클래스에 있는 getter 또는 setter의 동작을 확장하기 어렵다는 것입니다.겟터/세터

기능을 실제로 입수할 수 있습니다(예:

class C(object):
    _p = 1
    @property
    def p(self):
        return self._p
    @p.setter
    def p(self, val):
        self._p = val

는 'getter', 'setter'로 접근할 수.C.p.fget ★★★★★★★★★★★★★★★★★」C.p.fset그러나 일반 방법 상속(예: 슈퍼) 기능을 사용하여 쉽게 확장할 수 없습니다.Super의 복잡성을 좀 더 자세히 살펴본 후, Super를 실제로 다음과 같이 사용할 수 있습니다.

# Using super():
class D(C):
    # Cannot use super(D,D) here to define the property
    # since D is not yet defined in this scope.
    @property
    def p(self):
        return super(D,D).p.fget(self)

    @p.setter
    def p(self, val):
        print 'Implement extra functionality here for D'
        super(D,D).p.fset(self, val)

# Using a direct reference to C
class E(C):
    p = C.p

    @p.setter
    def p(self, val):
        print 'Implement extra functionality here for E'
        C.p.fset(self, val)

그러나 super()를 사용하면 속성을 재정의해야 하고 p의 언바인드 복사를 얻으려면 약간 반직관적인 super(cls, cls) 메커니즘을 사용해야 하기 때문에 매우 복잡합니다.

속성을 사용하는 것이 더 직관적이고 대부분의 코드에 더 적합합니다.

비교하는

o.x = 5
ox = o.x

대.

o.setX(5)
ox = o.getX()

어느 쪽이 더 읽기 쉬운지 알 수 있습니다.또한 속성을 통해 개인 변수를 훨씬 쉽게 만들 수 있습니다.

부동산이란, 실제로 필요할 때만 글쓰기나 세터의 오버헤드를 얻을 수 있도록 하는 것이라고 생각합니다.

Java Programming culture는 절대 속성에 접근하지 말고 getters와 setters, 그리고 실제로 필요한 것만을 거치도록 강력히 권고한다.이 명백한 코드 조각을 항상 쓰는 것은 다소 장황한 일이지만 70%는 사소한 논리로 대체되지 않는다는 것을 알 수 있습니다.

Python 에서는, 실제로 이러한 오버헤드를 배려하고 있기 때문에, 다음의 방법을 채용할 수 있습니다.

  • getter 및 setter가 필요하지 않은 경우 처음에는 사용하지 마십시오.
  • @property코드의 나머지 구문을 변경하지 않고 구현합니다.

저는 대부분의 경우 어느 쪽도 사용하지 않는 것을 선호합니다.속성의 문제는 클래스를 투명하게 하지 않는다는 것입니다.특히 세터에서 예외를 제기할 경우 문제가 됩니다.예를 들어 Account.email 속성이 있는 경우:

class Account(object):
    @property
    def email(self):
        return self._email

    @email.setter
    def email(self, value):
        if '@' not in value:
            raise ValueError('Invalid email address.')
        self._email = value

그러면 클래스 사용자는 속성에 값을 할당하면 예외가 발생할 수 있다고 예상하지 않습니다.

a = Account()
a.email = 'badaddress'
--> ValueError: Invalid email address.

그 결과 예외가 처리되지 않고 콜 체인으로 너무 많이 전파되어 적절하게 처리되지 않거나 프로그램 사용자에게 매우 도움이 되지 않는 트레이스 백이 표시될 수 있습니다(비록 python과 java의 세계에서는 너무 일반적입니다).

getter와 setter도 사용하지 않도록 하겠습니다.

  • 모든 속성에 대해 미리 정의하는 것은 시간이 많이 걸리기 때문입니다.
  • 불필요하게 코드의 양을 길게 하기 때문에 코드의 이해와 유지보수가 어려워집니다.
  • 필요에 따라서만 속성을 정의하면 클래스의 인터페이스가 변경되어 클래스의 모든 사용자에게 피해를 줍니다.

속성 및 getters/setters 대신 검증 방법 등 잘 정의된 장소에서 복잡한 로직을 수행하는 것이 좋습니다.

class Account(object):
    ...
    def validate(self):
        if '@' not in self.email:
            raise ValueError('Invalid email address.')

또는 유사한 Account.save 메서드를 사용합니다.

저는 속성이 유용한 경우가 없다는 것이 아니라, 수업이 필요 없을 정도로 단순하고 투명하게 진행된다면 더 잘 살 수 있다는 것을 말하고자 합니다.

Adam DonohueNeilenMarais속성이 디스크립터 클래스의 바인드 메서드라는 것을 아무도 언급하지 않은 것에 놀랐습니다.게터와 세터는 함수이며, 다음과 같은 용도로 사용할 수 있습니다.

  • 입증하다
  • 데이터를 변경하다
  • duck type(다른 type

이를 통해 구현 세부사항 및 코드 크러프트를 정규 표현, 유형 캐스트, 시도 등 스마트하게 숨길 수 있습니다.블록, 어설션 또는 계산된 값을 제외한다.

일반적으로 객체에서 CRUD를 수행하는 것은 매우 일상적인 일이지만 관계형 데이터베이스에 유지되는 데이터의 예를 생각해 보십시오.ORM은 속성 클래스에서 정의된 fget, fset, fdel 메서드에서 특정 SQL 언어의 구현 세부사항을 숨길 수 있습니다. 】【 】【 】【 】【 】【 】【 】【 】【 】【 【 】【 】【 】【 】【 】【 】【 】【 【 】【 】【 【 】【 】【 【 】【 】【 【 】코드로 매우 .self.variable = something또한 ORM을 사용하는 개발자의 세부사항을 생략합니다.

속성을 속박과 규율 언어(자바)의 따분한 흔적으로만 생각한다면 기술자의 요점을 놓치는 것이다.

다.@property전통적인 게터나 세터에는 장점이 있습니다.사용 사례에 따라 다릅니다.

점점의 @property

  • 데이터 액세스 구현을 변경하는 동안 인터페이스를 변경할 필요가 없습니다.프로젝트의 규모가 작을 경우 직접 속성 액세스를 사용하여 클래스 구성원에 액세스할 수 있습니다., 있다, 있다, 이런 foo입입 of Foo 있습니다.num 이 를 '이 멤버'로 얻을 수 있습니다.num = foo.num프로젝트가 커짐에 따라 간단한 속성 액세스에 대한 체크 또는 디버깅이 필요할 수 있습니다. 이렇게 .@property 학급 내에서.데이터 액세스인터페이스는 그대로 유지되므로 클라이언트코드를 변경할 필요가 없습니다.

    PEP-8에서 인용:

    단순한 퍼블릭 데이터 속성의 경우 복잡한 접근자/변환자 방식 없이 속성 이름만 노출하는 것이 가장 좋습니다.Python은 단순한 데이터 속성이 기능 동작을 확장해야 하는 경우 향후 기능 향상을 위한 쉬운 경로를 제공합니다.이 경우 속성을 사용하여 단순한 데이터 속성 액세스 구문 뒤에 기능 구현을 숨깁니다.

  • 「」를 사용합니다.@propertyPython에서의 데이터 액세스를 Pythonic으로 간주합니다.

    • Python(Java가 아닌) 프로그래머로서의 자기 정체성을 강화할 수 있습니다.

    • 면접관이 Java 스타일의 getter와 setter가 반패턴이라고 생각하는 경우 면접에 도움이 될 수 있습니다.

기존 게터 및 세터의 장점

  • 기존의 게터 및 세터에서는 단순한 속성 액세스보다 더 복잡한 데이터 액세스가 가능합니다.예를 들어, 클래스 멤버를 설정할 때, 어떤 것이 완벽해 보이지 않더라도 이 작업을 강제로 수행할 위치를 나타내는 플래그가 필요할 수 있습니다. like음음음음 access access access access access like like like like like like like like like like like like like like like like like like access access .foo.num = num 해서 수 있습니다.force★★★★★★★★★★★★★★★★★★:

    def Foo:
        def set_num(self, num, force=False):
            ...
    
  • 기존의 getters 및 setters에서는 클래스 멤버의 액세스가 메서드를 경유하는 것을 명확하게 하고 있습니다.이것은 다음을 의미합니다.

    • 그 결과 얻을 수 있는 것은 그 클래스에 정확히 저장되어 있는 것과 다를 수 있습니다.

    • 액세스가 단순한 속성 액세스처럼 보여도 성능은 그것과 크게 다를 수 있습니다.

    가 「」를 하지 않는 한.@property모든 속성 액세스 스테이트먼트 뒤에 숨김으로써 클래스 사용자의 놀라움을 최소화할 수 있습니다.

  • @NeilenMarais와 투고에서 언급했듯이 기존 getter와 setter를 서브클래스로 확장하는 것은 속성을 확장하는 것보다 쉽습니다.

  • 전통적인 게터와 세터는 여러 언어로 오랫동안 널리 사용되어 왔다.을 가진 팀에 , 해 보입니다.@property 성장함에 에서 Python이 없는 @property겟터 세터

주의사항

  • 다 아니다.@property또한 기존 getters 및 setters는 이름 앞에 이중 밑줄을 사용하더라도 클래스 멤버를 비공개로 만들지 않습니다.

    class Foo:
        def __init__(self):
            self.__num = 0
    
        @property
        def num(self):
            return self.__num
    
        @num.setter
        def num(self, num):
            self.__num = num
    
        def get_num(self):
            return self.__num
    
        def set_num(self, num):
            self.__num = num
    
    foo = Foo()
    print(foo.num)          # output: 0
    print(foo.get_num())    # output: 0
    print(foo._Foo__num)    # output: 0
    

복잡한 프로젝트에서는 명시적 세터 기능이 있는 읽기 전용 속성(또는 게터)을 사용하는 것이 좋습니다.

class MyClass(object):
...        
@property
def my_attr(self):
    ...

def set_my_attr(self, value):
    ...

장기간의 프로젝트에서는 코드를 작성하는 것보다 디버깅 및 리팩터링이 더 오래 걸립니다. 사용하다 보면 몇 가지 .@property.setter이치노

1) python을 사용하면 기존 객체의 새로운 속성을 만들 수 있습니다.따라서 다음 오식자를 추적하기가 매우 어렵습니다.

my_object.my_atttr = 4.

오브젝트가 복잡한 알고리즘일 경우 컨버전스가 되지 않는 이유를 알아내기 위해 상당한 시간을 소비합니다(위 행에 't'가 추가되어 있음).

2) 세터는 때때로 복잡하고 느린 방법(예: 데이터베이스 타격)으로 발전할 수 있다.다른 개발자가 왜 다음 기능이 매우 느린지 알아내는 것은 매우 어렵습니다.는 프로파일링에 .do_something(), 「」, 「」)my_object.my_attr = 4.실제로 속도가 느려지는 원인입니다.

def slow_function(my_object):
    my_object.my_attr = 4.
    my_object.do_something()

다음은 "Effective Python: 90 Specific Ways to Write Better Python"(놀라운 책)에서 발췌한 것입니다.적극 추천합니다).

주의사항

§ 단순한 퍼블릭애트리뷰트를 사용하여 새로운 클래스인터페이스를 정의하고 setter 메서드와 getter 메서드를 정의하지 않도록 합니다.

§ 필요에 따라 @property를 사용하여 오브젝트에서 Atribute에 액세스 할 때의 특별한 동작을 정의합니다.

① @property 메서드에서 이상한 부작용을 피하고 덜 놀랍다는 규칙을 따르세요.

§ @property 메서드가 빠른지 확인합니다.느리거나 복잡한 작업(특히 I/O를 수반하거나 부작용을 일으키는 작업)에는 일반 메서드를 사용합니다.

@property의 고급이지만 일반적인 용도는 한때 단순한 수치 속성이었던 것을 온 더 플라이 계산으로 전환하는 것입니다.이것은, 기존의 모든 클래스의 사용 상황을 이행 해, 콜 사이트를 재작성할 필요 없이 새로운 동작을 취할 수 있기 때문에 매우 도움이 됩니다(이것은, 특히 제어할 수 없는 발신 코드가 있는 경우에 중요합니다).또, @syslog 는, 시간이 지남에 따라 인터페이스를 개선하기 위한 중요한 미봉책이기도 합니다.

특히 @property는 시간이 지남에 따라 더 나은 데이터 모델로 점진적으로 발전할 수 있기 때문에 좋아합니다.
@module은 실제 코드에서 발생할 수 있는 문제에 대처하는 데 도움이 되는 도구입니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★@property 메서드를 반복적으로 확장하고 있는 자신을 발견했을 때, 코드의 부실한 디자인을 더 이상 강조할 것이 아니라 클래스를 재팩터링해야 할 때일 것입니다.

§ @property를 사용하여 기존 인스턴스 속성에 새로운 기능을 부여합니다.

§ @property를 사용하여 보다 나은 데이터 모델을 향해 점진적으로 전진한다.

§ @property를 너무 많이 사용하는 경우 클래스 및 모든 콜사이트를 리팩터링하는 것을 고려해 주십시오.

언급URL : https://stackoverflow.com/questions/6618002/using-property-versus-getters-and-setters

반응형