백엔드 개발 파이썬 튜토리얼 Python 설명자 시작하기

Python 설명자 시작하기

Dec 05, 2016 pm 01:27 PM
python

나는 오랫동안 Flask 코드에 대해 글을 쓰지 않았습니다. 생각하면 정말 부끄럽습니다. 하지만 이번에도 Flask에 대해 글을 쓰지 않을 것입니다. 나 (넌 정말 나쁜 년이야, 할 수 있으면 나를 물어라)

이번에는 Python에서 매우 중요한 것, 즉 Descriptor에 대해 써보겠습니다

설명어에 대한 첫 소개

과거의 법칙, Talk는 싸다, 코드를 먼저 살펴보자

classPerson(object):
""""""

#----------------------------------------------------------------------
def__init__(self, first_name, last_name):
"""Constructor"""
 self.first_name = first_name
 self.last_name = last_name

#----------------------------------------------------------------------
 @property
deffull_name(self):
"""
 Return the full name
 """
return"%s %s"% (self.first_name, self.last_name)

if__name__=="__main__":
 person = Person("Mike","Driscoll")
 print(person.full_name)
# 'Mike Driscoll'
 print(person.first_name)
# 'Mike'

로그인 후 복사
로그인 후 복사

이 세대, 뭐 재산에 대해서는 다들 잘 아실 텐데, 혹시 모르시는 분들도 계시겠지만, 재산의 구현 메커니즘을 아시나요? 무엇이 명확하지 않습니까? 파이썬을 배워보는 것은 어떨까요? . . 농담입니다. 다음 코드를 살펴보겠습니다.

classProperty(object):
"Emulate PyProperty_Type() in Objects/descrobject.c"
def__init__(self, fget=None, fset=None, fdel=None, doc=None):
 self.fget = fget
 self.fset = fset
 self.fdel = fdel
ifdocisNoneandfgetisnotNone:
 doc = fget.__doc__
 self.__doc__ = doc

def__get__(self, obj, objtype=None):
ifobjisNone:
returnself
ifself.fgetisNone:
raiseAttributeError("unreadable attribute")
returnself.fget(obj)

def__set__(self, obj, value):
ifself.fsetisNone:
raiseAttributeError("can't set attribute")
 self.fset(obj, value)

def__delete__(self, obj):
ifself.fdelisNone:
raiseAttributeError("can't delete attribute")
 self.fdel(obj)

defgetter(self, fget):
returntype(self)(fget, self.fset, self.fdel, self.__doc__)

defsetter(self, fset):
returntype(self)(self.fget, fset, self.fdel, self.__doc__)

defdeleter(self, fdel):
returntype(self)(self.fget, self.fset, fdel, self.__doc__)

로그인 후 복사

복잡해 보이지 않나요? 차근차근 살펴볼까요? 그러나 여기서 먼저 결론을 내립니다. 설명자는 __get__, __set__ 및 __delete__의 세 가지 특수 메서드를 구현하는 특수 개체입니다.

설명자 상세설명

부동산에 대해 이야기

위에서는 속성 구현 코드를 제공했는데 이제 이에 대해 자세히 설명하겠습니다

classPerson(object):
""""""

#----------------------------------------------------------------------
def__init__(self, first_name, last_name):
"""Constructor"""
 self.first_name = first_name
 self.last_name = last_name

#----------------------------------------------------------------------
 @property
deffull_name(self):
"""
 Return the full name
 """
return"%s %s"% (self.first_name, self.last_name)

if__name__=="__main__":
 person = Person("Mike","Driscoll")
 print(person.full_name)
# 'Mike Driscoll'
 print(person.first_name)
# 'Mike'

로그인 후 복사
로그인 후 복사

우선, 데코레이터에 대해 모르신다면 이 글을 읽어보시면 좋을 것 같습니다. 간단히 말해서, 공식적으로 코드를 실행하기 전에 우리 통역사가 데코레이터와 관련된 부분을 스캔할 것입니다. 클래스 데코레이터도 마찬가지입니다. 위에서 이 코드는

@Property
deffull_name(self):
"""
 Return the full name
 """
return"%s %s"% (self.first_name, self.last_name)
로그인 후 복사

은 이러한 프로세스, 즉 full_name=Property(full_name)를 트리거합니다. 그런 다음 나중에 객체를 인스턴스화한 후 person.full_name을 호출합니다. 이 프로세스는 실제로 person.full_name.__get__(person)과 동일하며 __get__() 메서드에 작성된 반환 self.fget(obj)을 트리거합니다. 위는 우리가 작성한 def full_name의 실행 코드입니다.

이때 동지들은 getter(), setter(), deleter()=의 구체적인 작동 메커니즘에 대해 생각해 볼 수 있습니다. =아직 궁금한 점이 있으시면 댓글로 편하게 토론해주세요.

설명자 정보

앞서 언급한 정의를 기억하세요. 설명자는 __get__, __set__ 및 __delete__라는 세 가지 특별한 메서드를 구현하는 특별한 종류의 객체입니다. 그런 다음 공식 Python 문서 설명에는 설명자의 중요성을 반영하기 위해 다음 단락이 있습니다. "설명자는 속성, 메서드, 정적 메서드, 클래스 메서드 및 super() 뒤에 있는 메커니즘입니다. Python 전체에서 사용됩니다. 버전 2.2에 도입된 새로운 스타일 클래스를 구현하기 위해 자체적으로 설명합니다. 간단히 말해서 설명자가 먼저 있고 그 다음이 air입니다. 새로운 스타일의 클래스에서는 속성, 메서드 호출, 정적 메서드, 클래스 메서드 등이 모두 설명자의 특정 사용을 기반으로 합니다.

자, 설명어가 왜 그렇게 중요한지 물어보고 싶을 수도 있습니다. 걱정하지 마시고 계속 시청해 보세요

설명자 사용

먼저 다음 코드를 살펴보세요

classA(object):#참고: Python 3.x 버전에서는 새 클래스를 사용하기 위해 객체 클래스에서 상속을 명시적으로 지정할 필요가 없습니다. Python 2.X(x> 2) 버전이 필요합니다

defa(self):
pass
if__name__=="__main__":
 a=A()
 a.a()
로그인 후 복사

모두들 a.a()라는 진술이 있다는 것을 알아차렸습니다. 이제 생각해 보세요. 이 메소드를 호출하면 어떻게 될까요?

알았나요? 아직 알아냈나요? 아니요? 알았어 계속하자

우선, 속성이 멤버이든 메서드이든 상관없이 속성을 호출할 때 __getattribute__() 속성을 호출하는 메서드를 트리거합니다. 호출이 구현되었습니다. 설명자 프로토콜은 호출 프로세스 type(a).__dict__['a'].__get__(b,type(b))를 생성합니다. 좋아, 여기에 또 다른 결론이 있습니다. "이러한 호출 프로세스에는 우선순위 순서가 있습니다. 호출하려는 속성이 데이터 설명자라면 이 속성이 인스턴스의 __dict__에 존재하는지 여부에 관계없이 사전에서 설명자의 __get__ 메서드가 먼저 호출됩니다. 호출하려는 속성이 데이터 설명자가 아닌 경우 인스턴스의 __dict__에 있는 기존 속성에 우선 순위를 부여합니다. 우리 클래스와 상위 클래스의 __dict__에 포함된 속성을 찾습니다. 속성이 존재하면 __get__() 메서드가 호출됩니다. 이해하기에는 조금 추상적인가요? 괜찮습니다. 곧 설명하겠지만 여기서는 먼저 데이터 설명자와 비데이터 설명자를 설명한 다음 예를 살펴봐야 합니다. 데이터 설명자와 비데이터 설명자는 무엇입니까? 실제로 설명자에서 __get__ 및 __set__ 프로토콜을 모두 구현하는 설명자는 __get__ 프로토콜만 구현된 경우 데이터 설명자가 아닙니다. 좋습니다. 이제 예를 살펴보겠습니다.

importmath
classlazyproperty:
def__init__(self, func):
 self.func = func

def__get__(self, instance, owner):
ifinstanceisNone:
returnself
else:
 value = self.func(instance)
 setattr(instance, self.func.__name__, value)
returnvalue
classCircle:
def__init__(self, radius):
 self.radius = radius
pass

 @lazyproperty
defarea(self):
 print("Com")
returnmath.pi * self.radius *2

deftest(self):
pass
if__name__=='__main__':
 c=Circle(4)
 print(c.area)

로그인 후 복사

好的,让我们仔细来看看这段代码,首先类描述符 @lazyproperty 的替换过程,前面已经说了,我们不在重复。接着,在我们第一次调用 c.area 的时候,我们首先查询实例 c 的 __dict__ 中是否存在着 area 描述符,然后发现在 c 中既不存在描述符,也不存在这样一个属性,接着我们向上查询 Circle 中的 __dict__ ,然后查找到名为 area 的属性,同时这是一个 non data descriptors ,由于我们的实例字典内并不存在 area 属性,那么我们便调用类字典中的 area 的 __get__ 方法,并在 __get__ 方法中通过调用 setattr 方法为实例字典注册属性 area 。紧接着,我们在后续调用 c.area 的时候,我们能在实例字典中找到 area 属性的存在,且类字典中的 area 是一个 non data descriptors ,于是我们不会触发代码里所实现的 __get__ 方法,而是直接从实例的字典中直接获取属性值。

描述符的使用

描述符的使用面很广,不过其主要的目的在于让我们的调用过程变得可控。因此我们在一些需要对我们调用过程实行精细控制的时候,使用描述符,比如我们之前提到的这个例子

classlazyproperty:
def__init__(self, func):
 self.func = func

def__get__(self, instance, owner):
ifinstanceisNone:
returnself
else:
 value = self.func(instance)
 setattr(instance, self.func.__name__, value)
returnvalue

def__set__(self, instance, value=0):
pass


importmath


classCircle:
def__init__(self, radius):
 self.radius = radius
pass

 @lazyproperty
defarea(self, value=0):
 print("Com")
ifvalue ==0andself.radius ==0:
raiseTypeError("Something went wring")

returnmath.pi * value *2ifvalue !=0elsemath.pi * self.radius *2

deftest(self):
pass

로그인 후 복사

利用描述符的特性实现懒加载,再比如,我们可以控制属性赋值的值

classProperty(object):
"Emulate PyProperty_Type() in Objects/descrobject.c"
def__init__(self, fget=None, fset=None, fdel=None, doc=None):
 self.fget = fget
 self.fset = fset
 self.fdel = fdel
ifdocisNoneandfgetisnotNone:
 doc = fget.__doc__
 self.__doc__ = doc

def__get__(self, obj, objtype=None):
ifobjisNone:
returnself
ifself.fgetisNone:
raiseAttributeError("unreadable attribute")
returnself.fget(obj)

def__set__(self, obj, value=None):
ifvalueisNone:
raiseTypeError("You can`t to set value as None")
ifself.fsetisNone:
raiseAttributeError("can't set attribute")
 self.fset(obj, value)

def__delete__(self, obj):
ifself.fdelisNone:
raiseAttributeError("can't delete attribute")
 self.fdel(obj)

defgetter(self, fget):
returntype(self)(fget, self.fset, self.fdel, self.__doc__)

defsetter(self, fset):
returntype(self)(self.fget, fset, self.fdel, self.__doc__)

defdeleter(self, fdel):
returntype(self)(self.fget, self.fset, fdel, self.__doc__)

classtest():
def__init__(self, value):
 self.value = value

 @Property
defValue(self):
returnself.value

 @Value.setter
deftest(self, x):
 self.value = x

로그인 후 복사

如上面的例子所描述的一样,我们可以判断所传入的值是否有效等等。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

뜨거운 기사 태그

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

DeepSeek Xiaomi를 다운로드하는 방법 DeepSeek Xiaomi를 다운로드하는 방법 Feb 19, 2025 pm 05:27 PM

DeepSeek Xiaomi를 다운로드하는 방법

템플릿의 장점과 단점은 무엇입니까? 템플릿의 장점과 단점은 무엇입니까? May 08, 2024 pm 03:51 PM

템플릿의 장점과 단점은 무엇입니까?

Google AI, 개발자를 위한 Gemini 1.5 Pro 및 Gemma 2 발표 Google AI, 개발자를 위한 Gemini 1.5 Pro 및 Gemma 2 발표 Jul 01, 2024 am 07:22 AM

Google AI, 개발자를 위한 Gemini 1.5 Pro 및 Gemma 2 발표

단 250달러에 Hugging Face의 기술 디렉터가 Llama 3를 단계별로 미세 조정하는 방법을 알려드립니다. 단 250달러에 Hugging Face의 기술 디렉터가 Llama 3를 단계별로 미세 조정하는 방법을 알려드립니다. May 06, 2024 pm 03:52 PM

단 250달러에 Hugging Face의 기술 디렉터가 Llama 3를 단계별로 미세 조정하는 방법을 알려드립니다.

여러 .NET 오픈 소스 AI 및 LLM 관련 프로젝트 프레임워크 공유 여러 .NET 오픈 소스 AI 및 LLM 관련 프로젝트 프레임워크 공유 May 06, 2024 pm 04:43 PM

여러 .NET 오픈 소스 AI 및 LLM 관련 프로젝트 프레임워크 공유

golang 함수 디버깅 및 분석에 대한 완벽한 가이드 golang 함수 디버깅 및 분석에 대한 완벽한 가이드 May 06, 2024 pm 02:00 PM

golang 함수 디버깅 및 분석에 대한 완벽한 가이드

당신은 그에게 Deepseek에게 어떻게 물어 봐요 당신은 그에게 Deepseek에게 어떻게 물어 봐요 Feb 19, 2025 pm 04:42 PM

당신은 그에게 Deepseek에게 어떻게 물어 봐요

평가 기능을 저장하는 방법 평가 기능을 저장하는 방법 May 07, 2024 am 01:09 AM

평가 기능을 저장하는 방법

See all articles