Home Backend Development Python Tutorial Getting Started with Python Descriptors

Getting Started with Python Descriptors

Dec 15, 2016 am 09:13 AM

I haven’t written about Flask code for a long time. I feel really ashamed when I think about it. However, I still won’t write about Flask this time. If you don’t accept it, come and beat me up (I’m such a bitch, bite me if you can)

I’ll do it this time Let’s write about a very important thing in Python, that is, Descriptor.

First introduction to descriptors

The old rule is, Talk is cheap, Show me the code. Let’s take a look at a piece of code first

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'
Copy after login
Copy after login


Everyone must be familiar with it. Well, who doesn’t know about property? But do you know the implementation mechanism of property? What’s unclear about it? Why don’t you learn Python? ah. . . Just kidding, let’s look at the following piece of code

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__)
Copy after login

Does it look complicated? It’s okay, let’s take a look at it step by step. But here we first give a conclusion: Descriptors are a special kind of object, which implements __get__, __set__, __delete__ these three special methods.

Detailed explanation of descriptors

Let’s talk about Property

In the above, we gave the Property implementation code, now let us talk about this in detail

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'
Copy after login
Copy after login

First of all, if you don’t know about decorators, you may Go read this article. In short, before we officially run the code, our interpreter will scan our code and replace the parts involving decorators. The same goes for class decorators. In the above, this code

@Property
deffull_name(self): 
""" 
 Return the full name 
 """
return"%s %s"% (self.first_name, self.last_name)
Copy after login

will trigger such a process, that is, full_name=Property(full_name) . Then after we instantiate the object later we call Person.full_name Such a process is actually equivalent to person.full_name.__get__(person) and then triggers __get__() The return self.fget(obj) written in the method is the execution code in def full_name that we originally wrote.

At this time, comrades can think about getter(), setter(), and deleter() The specific operating mechanism =. =If you still have questions, please feel free to discuss them in the comments.

About descriptors

Do you still remember the definition we mentioned before: Descriptors are a special kind of objects that implement __get__ , __set__ , __delete__ These three special methods. Then in the description of the official Python documentation, in order to reflect the importance of descriptors, there is this paragraph: "They are the mechanism behind properties, methods, static methods, class methods, and super(). They are used throughout Python itself to implement the new style classes introduced in version 2.2. ” In short, there is the descriptor first and then there is the sky, and every second there is air. . Well, in new-style classes, attributes, method calls, static methods, class methods, etc. are all based on the specific use of descriptors.

OK, you may want to ask, why are descriptors so important? Don't worry, let's continue to look at

Using descriptors

First, please look at the next piece of code

classA(object): #Note: In Python 3.x version, there is no need to explicitly specify the object from the use of new class class inherits, if in In the version of Python 2. what happened?

OK? Have you figured it out yet? No? Okay, let’s continue

First of all, when we call an attribute, whether it is a member or a method, we will trigger such a method to call the attribute __getattribute__(), in our In the __getattribute__() method, if the attribute we try to call implements our descriptor protocol, then such a calling process will occur type(a).__dict__['a'].__get__(b,type(b)) . Okay, here we have another conclusion: "In such a call process, there is such a priority order, if the attribute we are trying to call is a data descriptor , then regardless of whether this attribute exists in the __dict__ dictionary of our instance, the __get__ method in our descriptor will be called first. If the attribute we are trying to call is a non data descriptors, then we give priority to calling the existing attributes in __dict__ in our instance. If they do not exist, we will search up our class and __dict__ in the parent class according to the corresponding principles. Once the attribute exists, the __get__ method is called. If it does not exist, the __getattr__() method is called. Method". Is it a bit abstract to understand? It's okay, we will talk about it soon, but here, we first need to explain data descriptors and non data descriptors , let’s look at another example. What are data descriptors and non data descriptors? In fact, it is very simple. __get__ is also implemented in the descriptor. Descriptors with the __set__ protocol are data descriptors. If only the __get__ protocol is implemented, they are non data descriptors. . Okay, let’s look at an example now:

defa(self):
pass
if__name__=="__main__":
 a=A()
 a.a()
Copy after login

好的,让我们仔细来看看这段代码,首先类描述符 @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
Copy after login

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

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
Copy after login

   

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

以上就是Python 描述符(Descriptor)入门,更多相关文章请关注PHP中文网(www.php.cn)!


Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1663
14
PHP Tutorial
1264
29
C# Tutorial
1237
24
Python vs. C  : Applications and Use Cases Compared Python vs. C : Applications and Use Cases Compared Apr 12, 2025 am 12:01 AM

Python is suitable for data science, web development and automation tasks, while C is suitable for system programming, game development and embedded systems. Python is known for its simplicity and powerful ecosystem, while C is known for its high performance and underlying control capabilities.

The 2-Hour Python Plan: A Realistic Approach The 2-Hour Python Plan: A Realistic Approach Apr 11, 2025 am 12:04 AM

You can learn basic programming concepts and skills of Python within 2 hours. 1. Learn variables and data types, 2. Master control flow (conditional statements and loops), 3. Understand the definition and use of functions, 4. Quickly get started with Python programming through simple examples and code snippets.

Python: Games, GUIs, and More Python: Games, GUIs, and More Apr 13, 2025 am 12:14 AM

Python excels in gaming and GUI development. 1) Game development uses Pygame, providing drawing, audio and other functions, which are suitable for creating 2D games. 2) GUI development can choose Tkinter or PyQt. Tkinter is simple and easy to use, PyQt has rich functions and is suitable for professional development.

How Much Python Can You Learn in 2 Hours? How Much Python Can You Learn in 2 Hours? Apr 09, 2025 pm 04:33 PM

You can learn the basics of Python within two hours. 1. Learn variables and data types, 2. Master control structures such as if statements and loops, 3. Understand the definition and use of functions. These will help you start writing simple Python programs.

Python vs. C  : Learning Curves and Ease of Use Python vs. C : Learning Curves and Ease of Use Apr 19, 2025 am 12:20 AM

Python is easier to learn and use, while C is more powerful but complex. 1. Python syntax is concise and suitable for beginners. Dynamic typing and automatic memory management make it easy to use, but may cause runtime errors. 2.C provides low-level control and advanced features, suitable for high-performance applications, but has a high learning threshold and requires manual memory and type safety management.

Python and Time: Making the Most of Your Study Time Python and Time: Making the Most of Your Study Time Apr 14, 2025 am 12:02 AM

To maximize the efficiency of learning Python in a limited time, you can use Python's datetime, time, and schedule modules. 1. The datetime module is used to record and plan learning time. 2. The time module helps to set study and rest time. 3. The schedule module automatically arranges weekly learning tasks.

Python: Exploring Its Primary Applications Python: Exploring Its Primary Applications Apr 10, 2025 am 09:41 AM

Python is widely used in the fields of web development, data science, machine learning, automation and scripting. 1) In web development, Django and Flask frameworks simplify the development process. 2) In the fields of data science and machine learning, NumPy, Pandas, Scikit-learn and TensorFlow libraries provide strong support. 3) In terms of automation and scripting, Python is suitable for tasks such as automated testing and system management.

Python: Automation, Scripting, and Task Management Python: Automation, Scripting, and Task Management Apr 16, 2025 am 12:14 AM

Python excels in automation, scripting, and task management. 1) Automation: File backup is realized through standard libraries such as os and shutil. 2) Script writing: Use the psutil library to monitor system resources. 3) Task management: Use the schedule library to schedule tasks. Python's ease of use and rich library support makes it the preferred tool in these areas.

See all articles