산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> python

파이썬 @property 데코레이터

Python @property 데코레이터

이 튜토리얼에서는 Python @property 데코레이터에 대해 배웁니다. 객체 지향 프로그래밍에서 getter와 setter를 사용하는 파이썬적인 방법입니다.

Python 프로그래밍은 내장된 @property 객체 지향 프로그래밍에서 getter와 setter를 훨씬 쉽게 사용할 수 있게 해주는 데코레이터입니다.

@property에 대해 자세히 알아보기 전에 데코레이터는 처음부터 왜 필요한지 직관을 구축해 보겠습니다.

<시간>

게터와 세터가 없는 클래스

섭씨 온도를 저장하는 클래스를 만들기로 결정했다고 가정해 봅시다. 또한 온도를 화씨로 변환하는 방법을 구현합니다. 이를 수행하는 한 가지 방법은 다음과 같습니다.

class Celsius:
    def __init__(self, temperature = 0):
        self.temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

이 클래스에서 객체를 만들고 temperature을 조작할 수 있습니다. 속성:

# Basic method of setting and getting attributes in Python
class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32


# Create a new object
human = Celsius()

# Set the temperature
human.temperature = 37

# Get the temperature attribute
print(human.temperature)

# Get the to_fahrenheit method
print(human.to_fahrenheit())

출력

37
98.60000000000001

화씨로 변환할 때 추가 소수 자릿수는 부동 소수점 산술 오류로 인한 것입니다. 자세한 내용은 Python 부동 소수점 산술 오류를 참조하십시오.

temperature과 같은 객체 속성을 할당하거나 검색할 때마다 위에 표시된 것처럼 Python은 객체의 내장 __dict__에서 이를 검색합니다. 사전 속성.

>>> human.__dict__
{'temperature': 37}

따라서 man.temperature 내부적으로 man.__dict__['temperature']이 됩니다. .

<시간>

게터 및 세터 사용

섭씨의 유용성을 확장한다고 가정해 보겠습니다. 위에서 정의한 클래스. 우리는 어떤 물체의 온도도 섭씨 -273.15도(열역학의 절대 영도) 아래로 도달할 수 없다는 것을 알고 있습니다.

이 값 제약 조건을 구현하도록 코드를 업데이트합시다.

위의 제한 사항에 대한 확실한 해결책은 temperature 속성을 ​​숨기는 것입니다. (비공개로 설정) 새로운 getter 및 setter 메서드를 정의하여 조작합니다. 다음과 같이 할 수 있습니다.

# Making Getters and Setter methods
class Celsius:
    def __init__(self, temperature=0):
        self.set_temperature(temperature)

    def to_fahrenheit(self):
        return (self.get_temperature() * 1.8) + 32

    # getter method
    def get_temperature(self):
        return self._temperature

    # setter method
    def set_temperature(self, value):
        if value < -273.15:
            raise ValueError("Temperature below -273.15 is not possible.")
        self._temperature = value

우리가 볼 수 있듯이 위의 방법은 두 개의 새로운 get_temperature()set_temperature() 방법.

또한 temperature _temperature로 대체되었습니다. . 밑줄 _ 시작 부분은 Python에서 개인 변수를 나타내는 데 사용됩니다.

<시간>

이제 이 구현을 사용해 보겠습니다.

# Making Getters and Setter methods
class Celsius:
    def __init__(self, temperature=0):
        self.set_temperature(temperature)

    def to_fahrenheit(self):
        return (self.get_temperature() * 1.8) + 32

    # getter method
    def get_temperature(self):
        return self._temperature

    # setter method
    def set_temperature(self, value):
        if value < -273.15:
            raise ValueError("Temperature below -273.15 is not possible.")
        self._temperature = value


# Create a new object, set_temperature() internally called by __init__
human = Celsius(37)

# Get the temperature attribute via a getter
print(human.get_temperature())

# Get the to_fahrenheit method, get_temperature() called by the method itself
print(human.to_fahrenheit())

# new constraint implementation
human.set_temperature(-300)

# Get the to_fahreheit method
print(human.to_fahrenheit())

출력

37
98.60000000000001
Traceback (most recent call last):
  File "<string>", line 30, in <module>
  File "<string>", line 16, in set_temperature
ValueError: Temperature below -273.15 is not possible.

이 업데이트는 새로운 제한 사항을 성공적으로 구현했습니다. 더 이상 온도를 -273.15도 이하로 설정할 수 없습니다.

참고 :private 변수는 실제로 Python에 존재하지 않습니다. 따라야 할 규범이 있을 뿐입니다. 언어 자체에는 제한이 적용되지 않습니다.

>>> human._temperature = -300
>>> human.get_temperature()
-300

그러나 위 업데이트의 더 큰 문제는 이전 클래스를 구현한 모든 프로그램이 obj.temperature에서 코드를 수정해야 한다는 것입니다. obj.get_temperature()으로 obj.temperature = val과 같은 모든 표현식 obj.set_temperature(val)로 .

이 리팩토링은 수십만 줄의 코드를 처리하는 동안 문제를 일으킬 수 있습니다.

대체로 새로운 업데이트는 이전 버전과 호환되지 않았습니다. 여기가 @property입니다. 구하러 옵니다.

<시간>

속성 클래스

위의 문제를 처리하는 파이썬적인 방법은 property를 사용하는 것입니다. 수업. 코드를 업데이트하는 방법은 다음과 같습니다.

# using property class
class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

    # getter
    def get_temperature(self):
        print("Getting value...")
        return self._temperature

    # setter
    def set_temperature(self, value):
        print("Setting value...")
        if value < -273.15:
            raise ValueError("Temperature below -273.15 is not possible")
        self._temperature = value

    # creating a property object
    temperature = property(get_temperature, set_temperature)

print()를 추가했습니다. get_temperature() 내부의 함수 및 set_temperature() 그들이 처형되고 있음을 분명히 관찰하기 위해.

코드의 마지막 줄은 속성 개체를 temperature로 만듭니다. . 간단히 말해서 속성은 일부 코드를 첨부합니다(get_temperatureset_temperature ) 멤버 속성 액세스(temperature ).

이 업데이트 코드를 사용합시다:

# using property class
class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

    # getter
    def get_temperature(self):
        print("Getting value...")
        return self._temperature

    # setter
    def set_temperature(self, value):
        print("Setting value...")
        if value < -273.15:
            raise ValueError("Temperature below -273.15 is not possible")
        self._temperature = value

    # creating a property object
    temperature = property(get_temperature, set_temperature)


human = Celsius(37)

print(human.temperature)

print(human.to_fahrenheit())

human.temperature = -300

출력

Setting value...
Getting value...
37
Getting value...
98.60000000000001
Setting value...
Traceback (most recent call last):
  File "<string>", line 31, in <module>
  File "<string>", line 18, in set_temperature
ValueError: Temperature below -273 is not possible

보시다시피 temperature 값을 검색하는 모든 코드는 자동으로 get_temperature()를 호출합니다. 사전(__dict__) 조회 대신. 마찬가지로 temperature에 값을 할당하는 모든 코드 자동으로 set_temperature()을 호출합니다. .

set_temperature() 위에서도 볼 수 있습니다. 객체를 생성할 때도 호출되었습니다.

>>> human = Celsius(37)
Setting value...

이유를 짐작할 수 있습니까?

그 이유는 객체가 생성될 때 __init__() 메소드가 호출됩니다. 이 메서드에는 self.temperature = temperature 줄이 있습니다. . 이 표현식은 자동으로 set_temperature()를 호출합니다. .

마찬가지로 c.temperature과 같은 모든 액세스 자동으로 get_temperature() 호출 . 이것이 재산이 하는 일입니다. 다음은 몇 가지 예입니다.

>>> human.temperature
Getting value
37
>>> human.temperature = 37
Setting value

>>> c.to_fahrenheit()
Getting value
98.60000000000001

property 사용 , 우리는 값 제약의 구현에 수정이 필요하지 않음을 알 수 있습니다. 따라서 우리의 구현은 이전 버전과 호환됩니다.

참고 :실제 온도 값은 비공개 _temperature에 저장됩니다. 변하기 쉬운. temperature 속성은 이 개인 변수에 대한 인터페이스를 제공하는 속성 개체입니다.

<시간>

@property 데코레이터

파이썬에서는 property() property를 생성하고 반환하는 내장 함수입니다. 물체. 이 함수의 구문은 다음과 같습니다.

property(fget=None, fset=None, fdel=None, doc=None)

어디,

구현에서 볼 수 있듯이 이러한 함수 인수는 선택 사항입니다. 따라서 속성 객체는 다음과 같이 간단하게 생성할 수 있습니다.

>>> property()
<property object at 0x0000000003239B38>

속성 개체에는 getter()의 세 가지 메서드가 있습니다. , setter()deleter() fget를 지정하려면 , fsetfdel 나중에. 이는 다음과 같은 행을 의미합니다.

temperature = property(get_temperature,set_temperature)

다음과 같이 나눌 수 있습니다.

# make empty property
temperature = property()
# assign fget
temperature = temperature.getter(get_temperature)
# assign fset
temperature = temperature.setter(set_temperature)

이 두 코드는 동일합니다.

Python 데코레이터에 익숙한 프로그래머는 위의 구성을 데코레이터로 구현할 수 있음을 알 수 있습니다.

get_temperature 이름도 정의할 수 없습니다. 및 set_temperature 그것들은 불필요하고 클래스 네임스페이스를 오염시키기 때문입니다.

이를 위해 temperature를 재사용합니다. getter 및 setter 함수를 정의하는 동안 이름을 지정합니다. 이것을 데코레이터로 구현하는 방법을 살펴보겠습니다.

# Using @property decorator
class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

    @property
    def temperature(self):
        print("Getting value...")
        return self._temperature

    @temperature.setter
    def temperature(self, value):
        print("Setting value...")
        if value < -273.15:
            raise ValueError("Temperature below -273 is not possible")
        self._temperature = value


# create an object
human = Celsius(37)

print(human.temperature)

print(human.to_fahrenheit())

coldest_thing = Celsius(-300)

출력

Setting value...
Getting value...
37
Getting value...
98.60000000000001
Setting value...
Traceback (most recent call last):
  File "", line 29, in 
  File "", line 4, in __init__
  File "", line 18, in temperature
ValueError: Temperature below -273 is not possible

위의 구현은 간단하고 효율적입니다. property 사용을 권장하는 방법입니다. .


python

  1. 파이썬 데이터 유형
  2. 파이썬 연산자
  3. 파이썬 통과 문
  4. 파이썬 함수 인수
  5. 파이썬 사전
  6. 파이썬 상속
  7. 파이썬 연산자 오버로딩
  8. 파이썬 반복자
  9. 파이썬 클로저
  10. 파이썬 @property 데코레이터