>  기사  >  데이터 베이스  >  파이썬 설명자(1)

파이썬 설명자(1)

黄舟
黄舟원래의
2016-12-23 17:37:181169검색

Python 설명자는 관리 속성을 생성하는 방법입니다. 속성을 쿼리할 때마다 작업이 발생합니다. 이 작업의 기본값은 가져오기, 설정 또는 삭제입니다. 그러나 때로는 애플리케이션에

더 많은 요구 사항이 있어 더 복잡한 작업을 디자인해야 할 수도 있습니다. 가장 좋은 해결책은 원하는 작업을 수행하는 함수를 작성한 다음 속성에 액세스할 때 실행되도록 지정하는 것입니다. 이 기능을 가진 개체

를 설명자라고 합니다. 설명자는 Python 메서드, 바인딩된 메서드, super, PRperty, staticmethod 및 classmethod 구현의 기초입니다.

1. 디스크립터 프로토콜

디스크립터는 하나 이상의 __get__, __set__, __delete__ 메소드를 구현하여 메커니즘 후크에 액세스할 수 있는 객체입니다. 이러한 작업은 사용자 정의할 수도 있습니다.

__get__(self, instance, own): 속성에 액세스하고 속성 값을 반환하는 데 사용됩니다. Instance는 디스크립터를 사용하는 인스턴스 객체이고, own은 인스턴스가 속한 클래스입니다. 클래스를 통해 속성에 액세스할 때 인스턴스는 None입니다.

__set__(self, 인스턴스, 값): 속성 값을 설정합니다.

__delete__(self,instance): 속성 값을 삭제합니다.

2. 디스크립터 구현 방법

class Descriptor(object):
def __get__(self, instance, owner):
print 'getting:%s'%self. _Name Return Self._name
DEF __SET __ (Self, Instance, name):
Print' 설정:%s'%name
Self._name = name
stance ):

Print 'Deleting:%s'%Self._name
Del Self._name
클래스 Person(Object):
name = 설명()

매우 간단한 설명자 개체가 생성됩니다. 이제 Person 객체의 속성 이름을 읽고 설정하고 삭제할 수 있습니다:

>>> p=Person()

>> del p.name

deleting:john



참고: 설명자는 클래스 수준에서만 인스턴스화할 수 있으며 __init__() 및 기타 인스턴스 생성 설명자에서 각 설명자 개체에 대해 생성할 수 없습니다.

설명자가 있는 클래스에서 사용되는 속성 이름은 인스턴스에 저장된 속성 이름보다 우선순위가 높습니다. 설명자가 인스턴스에 값을 저장하려면 설명자 자체에서 사용하는 이름과 다른 이름을 선택해야 합니다.

위의 예와 같이 Person 클래스 초기화 __init__ 함수는 이름을 사용하여 인스턴스에 대한 속성을 설정할 수 없습니다.

데이터 설명자 및 비데이터 설명자:

__get__ 및 __set__이 구현되면 데이터 설명자이고, __get__만 구현되면 비데이터 설명자입니다. 다른 효과는 위와 같이 인스턴스를 통해 속성에 값을 할당할 때 데이터 디스크립터가 항상 인스턴스

의 속성 구현을 대체하고 비데이터 디스크립터에는 설정이 없다는 것입니다. p.name = ' hello'인 경우 __set__ 메서드는 더 이상 호출되지 않으며 인스턴스 속성 p.name은 'hello'로 직접 설정됩니다.

물론 __set__에서 AttributeError만 발생시키는 경우에도 여전히 비데이터 설명자를 얻게 됩니다.

설명자 호출 메커니즘:

객체의 a.attr 속성을 쿼리할 때 Python이 attr이 설명자 객체임을 확인한 경우 속성을 읽는 방법은 객체 a에 따라 다릅니다.

직접 호출: 가장 간단한 호출은 코드를 직접 사용하여 설명자 메서드 attr.__get__(a)를 호출하는 것입니다.

인스턴스 바인딩: a가 인스턴스 객체인 경우 메서드 호출: type( a).__dict__ ['attr'].__get__(a,type(a))

클래스 바인딩: A가 클래스 객체인 경우 메서드를 호출합니다. A.__dict__['attr'].__get__( None,A)

슈퍼 바인딩: a가 슈퍼 인스턴스인 경우 super(B,obj).m()은 obj.__class__.__mro__를 쿼리하여 B의 기본 클래스 A를 찾은 다음 A.__dict__를 실행합니다. ['m' ].__get__(obj,obj.__class__)

3. 속성 유형 검사를 수행하는 설명자

class TypedProperty(객체):
def __init__(self,name,attr_type,default=None):
self.name='_'+name
self.type=attr_type
self .default=default if default else attr_type()
def __get__(self,instance,own):
return getattr(instance,self.name,self.default)
def __set__(self,instance,value ):
그렇지 않은 경우 isinstance(value,self.type):
raise TypeError,'Must be %s'%self.type
setattr(instance,self.name,value)
def __delete__ (self,instance):
raise AttributeError('속성을 삭제할 수 없습니다')
class Foo(object):
name=TypedProperty('name',str)
num=TypedProperty('num ',int,37)                                                                                                           



위 설명자는 속성의 유형을 확인할 수 있습니다. name 속성이 str 유형으로 설정되지 않았거나 num이 int 유형으로 설정되지 않은 경우 오류가 발생합니다. 다음이 보고됩니다:

>>> f.name=21
TypeError:

이어야 하며 속성 삭제는 다음과 같습니다. 금지됨:

>>> del f.name

속성 오류: 속성을 삭제할 수 없습니다

f.name 보이지 않는 호출 유형(f).__dict__['name '].__get__(f,Foo), 즉 Foo.name.__get__(f,Foo)입니다.

위 설명자는 실제로 인스턴스에 저장됩니다. Name은 setattr(f,_name,value)를 통해 f._name에 저장되고, num은 f._num에 저장됩니다.


그렇지 않으면 설명자 이름 name이 인스턴스 속성 이름과 충돌하고 설명자 속성 f.name이 인스턴스 속성 f.name을 덮어씁니다.

위는 Python 디스크립터 디스크립터(1)의 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!

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