찾다
백엔드 개발파이썬 튜토리얼详解Python中的Descriptor描述符类

描述符是调和属性访问的一个类。描述符类可用来获取、设置或删除属性值。描述符对象是在类定义的时候构建在一个类中的。

一般来说,描述符是一个具有绑定行为的对象属性,其属性的访问被描述符协议方法覆写。这些方法是__get__()、 __set__()和__delete__(),一个对象中只要包含了这三个方法(译者注:包含至少一个),就称它为描述符。
属性访问的默认行为是从一个对象的字典中获取 (get)、设置 (set)、删除 (delete) 属性。例如:a.x 的查找链始于 a.__dict__['x'],然后是 type(a).__dict__['x'],然后是 type(a) 除元类之外的基类(译者注:如果继承树很深,可能会访问多个基类)。如果查找到的值是包含一个描述符方法的对象,那么Python可能会重写(该对象)的默认行为并调用那个描述符方法。注意只有在新式对象或者新式类(继承自object或者type)中描述符才会被调用。
描述符是一个功能强大、通用的协议。它们是属性、方法、静态方法、类方法、super()背后的实现机制。它们被广泛使用于Python 2.2中用来实现新式类。描述符简化了底层的C代码并为Python编程提供了一套灵活的新工具。

描述符设计模式有两个部分:一个所有者类和属性描述符本身。所有者类给它的属性使用一个或多个描述符。描述符类定义了获取、设置和删除方法的组合。描述符类的一个实例将会是所有者类的一个属性。

特性是基于所有者类的方法函数。描述符不像特性,是一个类的实例,与所有者类不同。因此,描述符通常是可重用的通用属性。所有者类可以有多个不同描述符类的实例来类管理具有相似行为的属性。

不像其他属性,描述符在类级别上创建。它们不是在__init()__初始化时创建。然而描述符的值可以在初始化期间设置,描述符通常是作为类的一部分,在任何方法函数之外来构建的。

当所有者类被定义时,每个描述符对象都是被绑定到一个不同的类级别属性的描述符类实例。

被确认为一个描述符,一个类必须实现以下三个方法的任意组合。

  • Descriptor.__get__(self, instance, owner) -> object:在这个方法中,instance参数是即将被访问的对象的self变量。owner参数是所有者类的对象。如果这个描述符在类的上下文中被调用,instance参数将得到一个None值。这必须返回描述符的值。
  • Descriptor.__set__(self, instance, value):在这个方法中,instance参数是即将被访问的对象的self变量。value参数是描述符需要设置的新值。
  • Descriptor.__delete__(self, instance)在这个方法中,instance参数是即将被访问的对象的self变量。该描述符的方法必须删除这个属性的值。

有时,一个描述符类还将需要一个__init__()方法函数来初始化描述符的内部状态。

有两种基于已定义方法的描述符,如下所示:

1.非数据描述符:这种描述符定义__set__()或__delete__()或两者皆有。它不能定义__get__()。非数据描述符对象往往会被用作表达式的一部分。它可能是一个可调用对象,或者它可能有自己的属性或方法。一个不可变的非数据描述符必须实现__set__(),但可能只是抛出AttributeError。这些描述符设计时很简单,因为接口更灵活。
2.数据描述符:这种描述符至少定义__get__()。通常,它定义__get__()和__set__()来创建一个可变对象。鉴于描述符将在很大程度上是不可见的,则不能更进一步的再定义属性或方法。属性的引用有一个数据描述符的数据被委托给描述符的__get__()、__set__()或__delete__()方法。这些是很难设计的,所以我们稍后来再看。
描述符有各种各样的用例。在内部,Python使用描述符有以下几个原因:

  • 在隐藏的内部,类的方法是作为描述符来实现。这些非数据描述符应用方法函数到对象以及不同的参数值。
  • property()函数通过给一个字段创建数据描述符来实现。
  • 一个类方法或静态方法被实现为一个描述符;这被应用到类中来代替类的实例。

当我们考虑一个描述符的目的,我们还必须为数据作为描述符可以正常工作来考察三种常见用例,如下所示:

  • 描述符对象有数据或获取到了数据。在这种情况下,描述符对象的self变量是有意义的且描述符是有状态的。数据描述符的__get__()方法返回这个内部数据。非数据描述符,描述符有其他方法或属性来访问这些数据。
  • 包含数据的所有者实例。在这种情况下,描述符对象必须使用instance参数来引用值到所有者对象中。数据描述符的__get__()方法从实例获取数据。非数据描述符有其他方法访问实例数据。
  • 包含相关数据的所有者类。在这种情况下,描述符对象必须使用owner参数。这是常用的当描述符实现了应用于整个类的静态方法或类方法。

我们将仔细看下第一种情况。我们看看创建带有__get__()和__set__()方法的数据描述符。我们也会看看创建没有__get__()方法的非数据描述符。

第二种情况(所有者实例中的数据)展示了@property装饰器都做了些什么。可能的优势是描述符有一个传统的特性将计算从拥有者类移到描述符类中。这倾向于分片类设计且可能不是最好的方法。如果计算是真正史诗般的复杂,策略模式可能会更好。

第三种情况展示@staticmethod和@classmethod装饰器是如何实现的。我们不需要重新发明轮子。

1、使用非数据描述符
我们经常会有一些紧密绑定了属性值的小对象。对于这个示例,我们将看看数值被绑定到单位的举措。

下面是一个简单的非数据描述符类,它缺少一个__get__()方法:

class UnitValue_1:
  """Measure and Unit combined."""
  def __init__(self, unit):
    self.value = None
    self.unit = unit
    self.default_format = "5.2f"

  def __set__(self, instance, value):
    self.value = value

  def __str__(self):
    return "{value:{spec}} {unit}"
    .format(spec=self.default_format, **self.__dict__)

  def __format__(self, spec="5.2f"):
    #print( "formatting", spec )
    if spec == "":
      spec = self.default_format
    return "{value:{spec}} {unit}".format(spec=spec, **self.__dict__)

这个类定义了一对简单的值,一个可变的(值),另一个是有效的不可变对象(单位)。

当这个描述符被访问时,描述符对象本身是可用的,且描述符的其他方法或属性可以被使用。我们可以使用这个描述符来创建类去管理尺寸和其他与物理单位有关的数值。

下面是一个类,做速度-时间-距离的及早计算:

class RTD_1:
  rate = UnitValue_1("kt")
  time = UnitValue_1("hr")
  distance = UnitValue_1("nm")
  def __init__(self, rate=None, time=None, distance=None):
    if rate is None:
      self.time = time
      self.distance = distance
      self.rate = distance / time
    if time is None:
      self.rate = rate
      self.distance = distance
      self.time = distance / rate
    if distance is None:
      self.rate = rate
      self.time = time
      self.distance = rate * time

  def __str__(self):
    return "rate: {0.rate} time: {0.time} distance:{0.distance}".format(self)

一旦对象被创建且属性被加载,丢失的值就已经被计算。一旦计算,描述符可以检查获取值或单位的名称。此外,描述符对str()有一个方便的响应和请求格式。

下面是描述符和RTD_1类之间的交互:

>>> m1 = RTD_1(rate=5.8, distance=12)
>>> str(m1)
'rate: 5.80 kt time: 2.07 hr distance: 12.00 nm'
>>> print("Time:", m1.time.value, m1.time.unit)
Time: 2.0689655172413794 hr

我们创建了一个带有rate和distance参数的RTD_1实例。这些都是用来计算rate和distance描述符的__set__()方法。

当我们请求str(m1),这会计算RTD_1的所有str()方法,转而使用rate、time和distance描述符的__format__()方法。这为我们提供了数字和单位。

鉴于非数据描述符没有__get__()且不返回其内部值,我们可以访问描述符的单个元素。

2、使用数据描述符
数据描述符设计要复杂一些,因为它对接口有限制。它必须有一个__get__()方法,且只能有__set__()或__delete__()。这是所有的接口:这些方法从一到三,没有其他方法。引入一个额外的方法意味着Python不会把该类当作一个正确的数据描述符。

我们会使用描述符设计一个简单的单位转换模式,可以在__get__()和__set__()方法做适当的转换。

下面是一个单位描述符的超类,它在其他单位和标准单位之间做转换:

class Unit:
  conversion = 1.0
  def __get__(self, instance, owner):
    return instance.kph * self.conversion

  def __set__(self, instance, value):
    instance.kph = value / self.conversion

该类用简单的乘法和除法将标准单位转换为其他非标准单位,反之亦然。

通过这个超类,我们可以从一个标准单位定义一些转换。在前面的示例,标准单位是千米时(公里/小时)。

以下是这两个转换描述符

class Knots(Unit):
  conversion = 0.5399568

class MPH(Unit):
  conversion = 0.62137119

继承方法非常有用。唯一改变的是转换因子。这些类可用于处理涉及单位转换的值。我们可以处理英里每小时或可交换的节点。下面是一个标准单位的单位描述符,公里每小时:

class KPH(Unit):

  def __get__(self, instance, owner):
    return instance._kph

  def __set__(self, instance, value):
    instance._kph = value

这个类代表一个标准,所以不做任何转换。它使用一个私有变量实例保存速度千米每小时的标准值。避免任何算术转换是一个简单的技术优化。避免任何一个公共字段的引用是至关重要的,来规避无限递归。

下面这个类,它对于一个给定的尺寸提供了一组转换:

class Measurement:
  kph = KPH()
  knots = Knots()
  mph = MPH()
  def __init__(self, kph=None, mph=None, knots=None):
    if kph:
      self.kph = kph
    elif mph:
      self.mph = mph
    elif knots:
      self.knots = knots
    else:
      raise TypeError

  def __str__(self):
    return "rate: {0.kph} kph = {0.mph} mph = {0.knots} knots".format(self)

对于不同的单位每个类级别的属性都是描述符。各种描述符的获取和设置方法会做适当的转换。我们可以使用这个类在各种单位之间进行速度转换。

以下是与Measurement类交互的一个例子:

>>> m2 = Measurement(knots=5.9)
>>> str(m2)
'rate: 10.92680006993152 kph = 6.789598762345432 mph = 5.9 knots'
>>> m2.kph
10.92680006993152
>>> m2.mph
6.789598762345432

我们通过设置不同的描述符创建了一个Measurement类的对象。在第一个示例中,我们设置了节点描述符。

当我们显示的值是一个大字符串,则每个描述符的__get__()都将被使用。这些方法从所有者对象获取内部kph字段值,应用一个转换因子,且返回一个结果值。

kph字段还使用了一个描述符。这个描述符不做任何转换;然而,它只是返回了缓存在所有者对象的私有值。KPH和Knots描述符要求所有者类实现一个kph属性。

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

Python의 유연성은 다중 파리가 지원 및 동적 유형 시스템에 반영되며, 사용 편의성은 간단한 구문 및 풍부한 표준 라이브러리에서 나옵니다. 유연성 : 객체 지향, 기능 및 절차 프로그래밍을 지원하며 동적 유형 시스템은 개발 효율성을 향상시킵니다. 2. 사용 편의성 : 문법은 자연 언어에 가깝고 표준 라이브러리는 광범위한 기능을 다루며 개발 프로세스를 단순화합니다.

파이썬 : 다목적 프로그래밍의 힘파이썬 : 다목적 프로그래밍의 힘Apr 17, 2025 am 12:09 AM

Python은 초보자부터 고급 개발자에 이르기까지 모든 요구에 적합한 단순성과 힘에 호의적입니다. 다목적 성은 다음과 같이 반영됩니다. 1) 배우고 사용하기 쉽고 간단한 구문; 2) Numpy, Pandas 등과 같은 풍부한 라이브러리 및 프레임 워크; 3) 다양한 운영 체제에서 실행할 수있는 크로스 플랫폼 지원; 4) 작업 효율성을 향상시키기위한 스크립팅 및 자동화 작업에 적합합니다.

하루 2 시간 안에 파이썬 학습 : 실용 가이드하루 2 시간 안에 파이썬 학습 : 실용 가이드Apr 17, 2025 am 12:05 AM

예, 하루에 2 시간 후에 파이썬을 배우십시오. 1. 합리적인 학습 계획 개발, 2. 올바른 학습 자원을 선택하십시오. 3. 실습을 통해 학습 된 지식을 통합하십시오. 이 단계는 짧은 시간 안에 Python을 마스터하는 데 도움이 될 수 있습니다.

Python vs. C : 개발자를위한 장단점Python vs. C : 개발자를위한 장단점Apr 17, 2025 am 12:04 AM

Python은 빠른 개발 및 데이터 처리에 적합한 반면 C는 고성능 및 기본 제어에 적합합니다. 1) Python은 간결한 구문과 함께 사용하기 쉽고 데이터 과학 및 웹 개발에 적합합니다. 2) C는 고성능과 정확한 제어를 가지고 있으며 게임 및 시스템 프로그래밍에 종종 사용됩니다.

파이썬 : 시간 약속과 학습 속도파이썬 : 시간 약속과 학습 속도Apr 17, 2025 am 12:03 AM

Python을 배우는 데 필요한 시간은 개인마다 다릅니다. 주로 이전 프로그래밍 경험, 학습 동기 부여, 학습 리소스 및 방법 및 학습 리듬의 영향을받습니다. 실질적인 학습 목표를 설정하고 실용적인 프로젝트를 통해 최선을 다하십시오.

파이썬 : 자동화, 스크립팅 및 작업 관리파이썬 : 자동화, 스크립팅 및 작업 관리Apr 16, 2025 am 12:14 AM

파이썬은 자동화, 스크립팅 및 작업 관리가 탁월합니다. 1) 자동화 : 파일 백업은 OS 및 Shutil과 같은 표준 라이브러리를 통해 실현됩니다. 2) 스크립트 쓰기 : PSUTIL 라이브러리를 사용하여 시스템 리소스를 모니터링합니다. 3) 작업 관리 : 일정 라이브러리를 사용하여 작업을 예약하십시오. Python의 사용 편의성과 풍부한 라이브러리 지원으로 인해 이러한 영역에서 선호하는 도구가됩니다.

파이썬과 시간 : 공부 시간을 최대한 활용파이썬과 시간 : 공부 시간을 최대한 활용Apr 14, 2025 am 12:02 AM

제한된 시간에 Python 학습 효율을 극대화하려면 Python의 DateTime, Time 및 Schedule 모듈을 사용할 수 있습니다. 1. DateTime 모듈은 학습 시간을 기록하고 계획하는 데 사용됩니다. 2. 시간 모듈은 학습과 휴식 시간을 설정하는 데 도움이됩니다. 3. 일정 모듈은 주간 학습 작업을 자동으로 배열합니다.

파이썬 : 게임, Guis 등파이썬 : 게임, Guis 등Apr 13, 2025 am 12:14 AM

Python은 게임 및 GUI 개발에서 탁월합니다. 1) 게임 개발은 Pygame을 사용하여 드로잉, 오디오 및 기타 기능을 제공하며 2D 게임을 만드는 데 적합합니다. 2) GUI 개발은 Tkinter 또는 PYQT를 선택할 수 있습니다. Tkinter는 간단하고 사용하기 쉽고 PYQT는 풍부한 기능을 가지고 있으며 전문 개발에 적합합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 채팅 명령 및 사용 방법
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는