programing

파이썬에서 속성 기능을 사용하는 방법에 대한 실제 예는 무엇입니까?

newsource 2023. 7. 19. 21:24

파이썬에서 속성 기능을 사용하는 방법에 대한 실제 예는 무엇입니까?

사용 방법에 관심이 있습니다.@property파로으썬이▁i는 단지 코드일 입니다.나는 파이썬 문서를 읽었고, 내 생각에, 거기에 있는 예시는 단지 장난감 코드일 뿐입니다.

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

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

    @x.deleter
    def x(self):
        del self._x

포장을 통해 어떤 이점을 얻을 수 있는지 모르겠습니다._x부동산 장식가로 가득 찼습니다.다음과 같이 구현하면 어떨까요?

class C(object):
    def __init__(self):
        self.x = None

제 생각에, 부동산 기능은 상황에 따라 유용할 수 있습니다.하지만 언제?누가 저에게 실제 사례를 좀 보여주실 수 있나요?

다른 예로는 집합 속성의 유효성 검사/필터링(범위 내에 있거나 허용 가능하도록 강제함)과 복잡하고 빠르게 변화하는 용어에 대한 게으른 평가가 있습니다.

속성 뒤에 숨겨진 복잡한 계산:

class PDB_Calculator(object):
    ...
    @property
    def protein_folding_angle(self):
        # number crunching, remote server calls, etc
        # all results in an angle set in 'some_angle'
        # It could also reference a cache, remote or otherwise,
        # that holds the latest value for this angle
        return some_angle

>>> f = PDB_Calculator()
>>> angle = f.protein_folding_angle
>>> angle
44.33276

유효성 검사:

class Pedometer(object)
    ...
    @property
    def stride_length(self):
        return self._stride_length

    @stride_length.setter
    def stride_length(self, value):
        if value > 10:
            raise ValueError("This pedometer is based on the human stride - a stride length above 10m is not supported")
        else:
            self._stride_length = value

중 의 밑줄이 읽기 전용 속성을 입니다._x파이썬에서 일반적으로 개인(내부 사용)을 의미하지만 때때로 우리는 인스턴스 속성을 읽을 수 있고 쓸 수 있도록 쓰지 않기를 원합니다.property에 사용:

>>> class C(object):

        def __init__(self, x):
            self._x = x

        @property
        def x(self):
            return self._x

>>> c = C(1)
>>> c.x
1
>>> c.x = 2
AttributeError        Traceback (most recent call last)

AttributeError: can't set attribute

매우 실용적인 사용을 위해기사를 보세요.간단히 말해서, Python에서 일반적으로 명시적인 getter/setter 메서드를 어떻게 포기할 수 있는지 설명합니다. 왜냐하면 만약 당신이 어떤 단계에서 그것들이 필요하게 된다면 당신은 그것들을 사용할 수 있기 때문입니다.property원활한 구현을 위해.

제가 사용한 한 가지 방법은 데이터베이스에 저장된 느린 조회 값을 캐싱하는 것입니다.이것은 당신의 속성이 계산이나 당신이 온디맨드로만 하기를 원하는 다른 긴 작업(예: 데이터베이스 검사, 네트워크 통신)을 필요로 하는 모든 상황으로 일반화됩니다.

class Model(object):

  def get_a(self):
    if not hasattr(self, "_a"):
      self._a = self.db.lookup("a")
    return self._a

  a = property(get_a)

이것은 주어진 페이지 뷰에 이러한 종류의 특정 속성이 하나만 필요할 수 있는 웹 앱이었지만, 기본 객체 자체에는 몇 가지 속성이 있을 수 있습니다. 모든 속성을 초기화하는 것은 낭비가 될 것이고 속성은 게으른 속성과 그렇지 않은 속성을 유연하게 사용할 수 있습니다.

답변과 댓글을 읽어보면 단순하면서도 유용한 사례가 빠진 듯한 답변이 주요 주제인 것 같습니다.간단한 사용법을 보여주는 매우 간단한 것을 여기에 포함시켰습니다.@property단위를 사용하여 있는 클래스입니다. , 사용자가 거리 측정을 할 수 .in_feet또는in_metres.

class Distance(object):
    def __init__(self):
        # This private attribute will store the distance in metres
        # All units provided using setters will be converted before
        # being stored
        self._distance = 0.0

    @property
    def in_metres(self):
        return self._distance

    @in_metres.setter
    def in_metres(self, val):
        try:
            self._distance = float(val)
        except:
            raise ValueError("The input you have provided is not recognised "
                             "as a valid number")

    @property
    def in_feet(self):
        return self._distance * 3.2808399

    @in_feet.setter
    def in_feet(self, val):
        try:
            self._distance = float(val) / 3.2808399
        except:
            raise ValueError("The input you have provided is not recognised "
                             "as a valid number")

    @property
    def in_parsecs(self):
        return self._distance * 3.24078e-17

    @in_parsecs.setter
    def in_parsecs(self, val):
        try:
            self._distance = float(val) / 3.24078e-17
        except:
            raise ValueError("The input you have provided is not recognised "
                             "as a valid number")

용도:

>>> distance = Distance()
>>> distance.in_metres = 1000.0
>>> distance.in_metres
1000.0
>>> distance.in_feet
3280.8399
>>> distance.in_parsecs
3.24078e-14

속성은 특정 필드를 조작하고 미들웨어 계산을 수행하는 방법을 더 많이 제어할 수 있는 필드 주변의 추상화일 뿐입니다.몇 가지 생각나는 용도는 검증 및 사전 초기화 및 액세스 제한입니다.

@property
def x(self):
    """I'm the 'x' property."""
    if self._x is None:
        self._x = Foo()

    return self._x

예, 게시된 원래 예제의 경우 속성은 단순히 인스턴스 변수 'x'를 갖는 것과 정확히 동일하게 작동합니다.

이것이 파이썬 속성의 가장 좋은 점입니다.외부에서 보면 인스턴스 변수와 똑같이 작동합니다!클래스 외부에서 인스턴스 변수를 사용할 수 있습니다.

즉, 첫 번째 예제에서 인스턴스(instance) 변수를 실제로 사용할 수 있습니다.상황이 변경된 후 구현을 변경하기로 결정하고 속성이 유용한 경우에도 속성에 대한 인터페이스는 클래스 외부의 코드와 동일합니다.인스턴스 변수에서 속성으로 변경해도 클래스 외부의 코드에는 영향을 주지 않습니다.

많은 다른 언어와 프로그래밍 과정들은 프로그래머가 인스턴스 변수를 절대 노출해서는 안 되며, 대신 질문에 인용된 간단한 경우에도 클래스 외부에서 액세스할 수 있는 모든 값에 대해 '게터'와 '세터'를 사용하도록 지시합니다.

다양한 언어(예: Java)를 사용하는 클래스 외부 코드

object.get_i()
    #and
object.set_i(value)

#in place of (with python)
object.i
    #and 
object.i = value

클래스를 구현할 때 첫 번째 예와 정확히 일치하는 많은 '게터'와 '세터'가 있습니다. 즉, 단순 인스턴스 변수를 복제하는 것입니다.클래스 구현이 변경되면 클래스 외부의 모든 코드를 변경해야 하므로 이러한 게터 및 세터가 필요합니다.그러나 python 속성을 사용하면 클래스 외부의 코드가 인스턴스 변수와 동일할 수 있습니다.따라서 속성을 추가하거나 단순 인스턴스 변수가 있는 경우 클래스 외부의 코드를 변경할 필요가 없습니다.따라서 대부분의 객체 지향 언어와 달리, 간단한 예에서는 실제로 필요하지 않은 'getters'와 'setters' 대신 인스턴스 변수를 사용할 수 있습니다. 나중에 속성으로 변경하더라도 클래스를 사용하는 코드는 변경할 필요가 없습니다.

즉, 복잡한 동작이 있는 경우에만 속성을 생성하면 되며, 질문에 설명된 것처럼 간단한 인스턴스 변수만 사용하면 되는 매우 일반적인 단순한 경우에는 인스턴스 변수를 사용할 수 있습니다.

세터를 사용하는 것에 비해 속성의 또 다른 좋은 기능은 OP= 연산자(예: +=, -=, *= 등)를 속성에서 계속 사용하면서 세터와 게터가 제공하는 유효성 검사, 액세스 제어, 캐싱 등을 유지할 수 있다는 것입니다.

예를 들어, 당신이 수업을 썼다면.Person세터로setage(newage)그리고 더 좋은 사람getage()그런 다음 나이를 늘리려면 다음과 같이 기록해야 합니다.

bob = Person('Robert', 25)
bob.setage(bob.getage() + 1)

하지만 만약 당신이 만들었다면age당신이 훨씬 더 깨끗하게 쓸 수 있는 부동산:

bob.age += 1

당신의 질문에 대한 짧은 대답은, 당신의 예에서, 이익이 없다는 것입니다.속성이 포함되지 않은 양식을 사용해야 합니다.

속성이 존재하는 이유는 코드가 미래에 변경되고 갑자기 데이터로 더 많은 작업을 수행해야 하는 경우(캐시 값, 액세스 보호, 외부 리소스 쿼리)무엇이든 간에, 인터페이스를 변경하지 않고도 데이터에 대한 게터와 세터를 추가하도록 클래스를 쉽게 수정할 수 있으므로, 코드의 모든 부분에서 해당 데이터가 액세스되는 위치를 찾아 변경할 필요가 없습니다.

많은 사람들이 처음에 알아차리지 못하는 것은 자산의 하위 클래스를 만들 수 있다는 것입니다.이것은 읽기 전용 객체 속성 또는 읽고 쓸 수 있지만 제거할 수 없는 속성을 노출하는 데 매우 유용하다는 것을 알게 되었습니다.또한 객체 필드에 대한 수정사항 추적과 같은 기능을 래핑하는 훌륭한 방법입니다.

class reader(property):
    def __init__(self, varname):
        _reader = lambda obj: getattr(obj, varname)
        super(reader, self).__init__(_reader)

class accessor(property):
    def __init__(self, varname, set_validation=None):
        _reader = lambda obj: getattr(obj, varname)
        def _writer(obj, value):
            if set_validation is not None:
               if set_validation(value):
                  setattr(obj, varname, value)
        super(accessor, self).__init__(_reader, _writer)

#example
class MyClass(object):
   def __init__(self):
     self._attr = None

   attr = reader('_attr')

언급URL : https://stackoverflow.com/questions/6304040/real-world-example-about-how-to-use-property-feature-in-python