Programing

게터와 세터를 사용하는 파이썬적인 방법은 무엇입니까?

lottogame 2020. 3. 18. 07:59
반응형

게터와 세터를 사용하는 파이썬적인 방법은 무엇입니까?


나는 다음과 같이하고있다 :

def set_property(property,value):  
def get_property(property):  

또는

object.property = value  
value = object.property

저는 Python을 처음 사용하므로 여전히 구문을 탐색하고 있으며이 작업에 대한 조언을 원합니다.


이것을 시도하십시오 : 파이썬 속성

샘플 코드는 다음과 같습니다.

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

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

    @x.setter
    def x(self, value):
        print("setter of x called")
        self._x = value

    @x.deleter
    def x(self):
        print("deleter of x called")
        del self._x


c = C()
c.x = 'foo'  # setter called
foo = c.x    # getter called
del c.x      # deleter called

게터와 세터를 사용하는 파이썬적인 방법은 무엇입니까?

은 "파이썬"방법은 없다 "게터"와 "세터"를 사용하지만, 문제는 보여 같은 일반 속성을 사용하고, del역 참조를 위해 (그러나 이름은 무죄 ... 내장 명령을 보호하기 위해 변경) :

value = 'something'

obj.attribute = value  
value = obj.attribute
del obj.attribute

나중에 설정을 수정하고 가져 property오려면 데코레이터 를 사용하여 사용자 코드를 변경하지 않고도 변경할 수 있습니다 .

class Obj:
    """property demo"""
    #
    @property
    def attribute(self): # implements the get - this name is *the* name
        return self._attribute
    #
    @attribute.setter
    def attribute(self, value): # name must be the same
        self._attribute = value
    #
    @attribute.deleter
    def attribute(self): # again, name must be the same
        del self._attribute

(각 데코레이터는 이전 속성 객체를 복사하고 업데이트하므로 각 세트, 가져 오기 및 삭제 기능 / 방법에 대해 동일한 이름을 사용해야합니다.)

위를 정의한 후 원래 설정, 가져 오기 및 삭제는 동일합니다.

obj = Obj()
obj.attribute = value  
the_value = obj.attribute
del obj.attribute

이것을 피해야합니다 :

def set_property(property,value):  
def get_property(property):  

첫째, 속성이 (보통 self) 으로 설정된 인스턴스에 대한 인수를 제공하지 않기 때문에 위와 같이 작동하지 않습니다 .

class Obj:

    def set_property(self, property, value): # don't do this
        ...
    def get_property(self, property):        # don't do this either
        ...

둘째, 이것은 두 가지 특별한 방법 __setattr__목적을 복제합니다 __getattr__.

셋째, 우리는 또한이 setattrgetattr내장 기능.

    setattr(object, 'property_name', value)
    getattr(object, 'property_name', default_value)  # default is optional

@property장식은 getter 및 setter를 만드는 것입니다.

예를 들어 설정 동작을 수정하여 설정중인 값을 제한 할 수 있습니다.

    class Protective(object):

        @property
        def protected_value(self):
            return self._protected_value

        @protected_value.setter
        def protected_value(self, value):
            if acceptable(value): # e.g. type or range check
                self._protected_value = value

일반적으로 우리는 사용을 피하고 property직접 속성을 사용하려고 합니다.

이것은 파이썬 사용자가 기대하는 것입니다. 가장 놀랍게도 규칙에 따라 반대되는 이유가 없다면 사용자에게 기대하는 바를 제공해야합니다.

데모

예를 들어, 객체의 protected 속성이 0에서 100 사이의 정수 여야하고 사용자에게 적절한 사용법을 알려주는 적절한 메시지와 함께 삭제를 방지해야한다고 가정 해보십시오.

class Protective(object):
    def __init__(self, start_protected_value=0):
        self.protected_value = start_protected_value
    @property
    def protected_value(self):
        return self._protected_value
    @protected_value.setter
    def protected_value(self, value):
        if value != int(value):
            raise TypeError("protected_value must be an integer")
        if 0 <= value <= 100:
            self._protected_value = int(value)
        else:
            raise ValueError("protected_value must be " +
                             "between 0 and 100 inclusive")
    @protected_value.deleter
    def protected_value(self):
        raise AttributeError("do not delete, protected_value can be set to 0")

그리고 사용법 :

>>> p1 = Protective(3)
>>> p1.protected_value
3
>>> p1 = Protective(5.0)
>>> p1.protected_value
5
>>> p2 = Protective(-5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
  File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> p1.protected_value = 7.3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 17, in protected_value
TypeError: protected_value must be an integer
>>> p1.protected_value = 101
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> del p1.protected_value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 18, in protected_value
AttributeError: do not delete, protected_value can be set to 0

이름이 중요합니까?

예 그들은 . .setter그리고 .deleter원래 재산의 복사본을 만든다. 이를 통해 서브 클래스는 부모의 동작을 변경하지 않고 동작을 올바르게 수정할 수 있습니다.

class Obj:
    """property demo"""
    #
    @property
    def get_only(self):
        return self._attribute
    #
    @get_only.setter
    def get_or_set(self, value):
        self._attribute = value
    #
    @get_or_set.deleter
    def get_set_or_delete(self):
        del self._attribute

이제 이것이 작동하려면 해당 이름을 사용해야합니다.

obj = Obj()
# obj.get_only = 'value' # would error
obj.get_or_set = 'value'  
obj.get_set_or_delete = 'new value'
the_value = obj.get_only
del obj.get_set_or_delete
# del obj.get_or_set # would error

이것이 어디에 유용한 지 잘 모르겠지만 유스 케이스는 get, set 및 / 또는 delete-only 속성을 원하는 경우입니다. 이름이 같은 의미 적으로 동일한 속성을 고수하는 것이 가장 좋습니다.

결론

간단한 속성으로 시작하십시오.

나중에 설정, 가져 오기 및 삭제와 관련된 기능이 필요한 경우 속성 데코레이터를 사용하여 추가 할 수 있습니다.

피 기능은 이름 set_...get_...의 어떤 속성에 대한 것을 -.


In [1]: class test(object):
    def __init__(self):
        self.pants = 'pants'
    @property
    def p(self):
        return self.pants
    @p.setter
    def p(self, value):
        self.pants = value * 2
   ....: 
In [2]: t = test()
In [3]: t.p
Out[3]: 'pants'
In [4]: t.p = 10
In [5]: t.p
Out[5]: 20

@property데코레이터를 확인하십시오 .


사용 @property하고 @attribute.setter당신이 "파이썬"방법을 사용하는 것이 아니라 도움뿐만 아니라 속성의 유효성을 확인하는 두 개체를 만드는 동안이를 변경할 때.

class Person(object):
    def __init__(self, p_name=None):
        self.name = p_name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, new_name):
        if type(new_name) == str: #type checking for name property
            self._name = new_name
        else:
            raise Exception("Invalid value for name")

이를 통해 실제로 _name클라이언트 개발자로부터 속성을 '숨기기' 하고 이름 속성 유형을 확인합니다. 시작하는 동안에도이 접근 방식을 따르면 setter가 호출됩니다. 그래서:

p = Person(12)

다음으로 이어질 것입니다 :

Exception: Invalid value for name

그러나:

>>>p = person('Mike')
>>>print(p.name)
Mike
>>>p.name = 'George'
>>>print(p.name)
George
>>>p.name = 2.3 # Causes an exception

접근 자 / 뮤 테이터 (예 : @attr.setter@property)를 사용할 수 있지만 가장 중요한 것은 일관된 것입니다 !

PEP8 , 상속을위한 설계는 말합니다 :

단순한 공개 데이터 속성의 경우 복잡한 접근 자 / 돌연변이 방법없이 속성 이름 만 노출 하는 것이 가장 좋습니다 . 간단한 데이터 속성이 기능적 행동을 키워야한다는 것을 알면 파이썬은 미래의 개선을위한 쉬운 길을 제공한다는 것을 명심하십시오. 이 경우 간단한 데이터 속성 액세스 구문 뒤에 기능 구현을 숨기려면 속성을 사용하십시오.

반면, Google 스타일 가이드 Python 언어 규칙 / 속성에 따르면 권장 사항은 다음과 같습니다.

새 코드의 속성을 사용하여 일반적으로 단순하고 가벼운 접근 자 또는 세터 메서드를 사용했던 데이터에 액세스하거나 데이터를 설정하십시오. @property데코레이터로 속성을 만들어야합니다 .

이 접근법의 장점 :

간단한 속성 액세스를위한 명시적인 get 및 set 메소드 호출을 제거하여 가독성이 향상되었습니다. 계산이 지연 될 수 있습니다. 클래스의 인터페이스를 유지하는 파이썬 방식을 고려했습니다. 성능면에서 직접 변수 액세스가 합리적인 경우 속성을 허용하는 것은 사소한 접근 자 메서드를 필요로하지 않습니다. 또한 나중에 인터페이스를 손상시키지 않고 접근 자 메서드를 추가 할 수 있습니다.

그리고 단점 :

object파이썬 2에서 상속 받아야 합니다. 연산자 오버로딩과 같은 부작용을 숨길 수 있습니다. 서브 클래스를 혼동 할 수 있습니다.


당신은 마법의 방법을 사용할 수 있습니다 __getattribute____setattr__.

class MyClass:
    def __init__(self, attrvalue):
        self.myattr = attrvalue
    def __getattribute__(self, attr):
        if attr == "myattr":
            #Getter for myattr
    def __setattr__(self, attr):
        if attr == "myattr":
            #Setter for myattr

__getattr__그리고 __getattribute__동일하지 않음을 명심하십시오 . __getattr__속성을 찾을 수 없을 때만 호출됩니다.

참고 URL : https://stackoverflow.com/questions/2627002/whats-the-pythonic-way-to-use-getters-and-setters

반응형