게터와 세터를 사용하는 파이썬적인 방법은 무엇입니까? = object.property 저는 Python을

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

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            # first decorate the getter method
    def attribute(self): # This getter method name is *the* name
        return self._attribute
    #
    @attribute.setter    # the property decorates with `.setter` now
    def attribute(self, value):   # name, e.g. "attribute", is the same
        self._attribute = value   # the "value" name isn't special
    #
    @attribute.deleter     # decorate with `.deleter`
    def attribute(self):   # again, the method name is 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):
    """protected property demo"""
    #
    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")

(주는 __init__를 의미 self.protected_value하지만, 등록 방법을 참조하십시오 self._protected_value.이 때문에 즉__init__ 사용을 보장 공개 API를 통해 속성은 “보호”이다.)

그리고 사용법 :

>>> 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하고 @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


답변

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


답변

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

@property단순히 속성에 액세스하는 데 사용 하는 경우 ( 예 :

class myClass:
    def __init__(a):
        self._a = a

    @property
    def a(self):
        return self._a

이것을 사용하여 every * 속성 에 액세스하십시오 ! 접근자를 사용 하지 않고 일부 속성을 사용 @property하고 다른 속성을 공개 (예 : 밑줄없는 이름)로 두는 것은 좋지 않습니다. 예를 들어

class myClass:
    def __init__(a, b):
        self.a = a
        self.b = b

    @property
    def a(self):
        return self.a

참고 self.b 가 공공 비록 여기에서 명시 적으로 접근이 없습니다.

세터 (또는 뮤 테이터 ) 와 마찬가지로 자유롭게 사용 @attribute.setter하지만 일관성을 유지하십시오! 예를 들어

class myClass:
    def __init__(a, b):
        self.a = a
        self.b = b

    @a.setter
    def a(self, value):
        return self.a = value

당신의 의도를 추측하기가 어렵습니다. 한 손으로 당신은 두 말을하는지 a그리고 b내가 이론적 접근 / 개의 mutate (GET / SET) 모두 허용해야하므로 (이름에 선두에 밑줄) 공개됩니다. 하지만 당신은 단지에 대한 명시 뮤 테이터 지정 a어쩌면 내가 설정할 수 없습니다 것을 나에게 알려줍니다 b. 명시 적 뮤 테이터를 제공했기 때문에 명시 적 접근 자 ( @property) 가 부족 하여 해당 변수 중 하나에 액세스 할 수 없어야하는지 또는 단순히 사용하는 것에 대해 절박한 것인지 확실 하지 않습니다 @property.

* 일부 변수를 명시 적으로 액세스 가능하거나 변경 가능하게 만들거나 두 가지 모두 허용하지 않으려는 경우 또는 속성에 액세스하거나 변경할 때 추가 논리를 수행하려는 경우는 예외입니다 . 이것은 내가 개인적으로 사용 @property하고있는 경우입니다 @attribute.setter(그렇지 않으면 공개 속성에 대한 명시 적 후임 / 뮤 테이터가 없음).

마지막으로 PEP8 및 Google 스타일 가이드 제안 :

상속을위한 디자인 PEP8 은 다음과 같이 말합니다.

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

반면, 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__속성을 찾을 수 없을 때만 호출됩니다.