Table of Contents
Class Attributes/Methods
Descriptor Protocol
Why is self in the method definition?
Home Backend Development Python Tutorial What is the self parameter in Python?

What is the self parameter in Python?

May 08, 2023 pm 05:49 PM
python elf

Python 的"self"参数是什么?

Let’s start with what we already know: self - the first parameter in the method - refers to the class instance:

class MyClass:
┌─────────────────┐
▼ │
def do_stuff(self, some_arg): │
print(some_arg)▲│
 ││
 ││
 ││
 ││
instance = MyClass() ││
instance.do_stuff("whatever") │
│ │
└───────────────────────────────┘
Copy after login

Also, this argument doesn't actually have to be called self - it's just a convention. For example, you can use it as is common in other languages.

The above code may be natural and obvious because you have been using it, but we only gave .do_stuff() one argument (some_arg), but the method declares two (self and, some_arg) , it doesn’t seem to make sense. The arrow in the snippet shows that self is translated into an instance, but how is it actually passed?

instance = MyClass()
MyClass.do_stuff(instance, "whatever")
Copy after login

What Python does internally is convert instance.do_stuff("whatever") to MyClass.do_stuff(instance, "whatever"). We could call it "Python magic" here, but if we want to really understand what's going on behind the scenes, we need to understand what Python methods are and how they relate to functions.

Class Attributes/Methods

In Python, there is no such thing as a "method" object - in fact methods are just regular functions. The difference between functions and methods is that methods are defined in the namespace of a class, making them properties of that class.

These attributes are stored in the class dictionary __dict__ and we can access them directly or using the vars built-in function:

MyClass.__dict__["do_stuff"]
# <function MyClass.do_stuff at 0x7f132b73d550>
vars(MyClass)["do_stuff"]
# <function MyClass.do_stuff at 0x7f132b73d550>
Copy after login

The most common way to access them is the "class method ” Way:

print(MyClass.do_stuff)
# <function MyClass.do_stuff at 0x7f132b73d550>
Copy after login

Here we access the function using the class attribute and as expected print do_stuff is a function of MyClass. However, we can also access it using instance properties:

print(instance.do_stuff)
# <bound method MyClass.do_stuff of <__main__.MyClass object at 0x7ff80c78de50>
Copy after login

But in this case, we get a "bound method" instead of the original function. What Python does for us here is that it binds class attributes to instances, creating what are called "binding methods". This "bound method" is a wrapper around the underlying function, which already inserts the instance as the first argument (self).

Thus, methods are ordinary functions with a class instance (self) appended to their other parameters.

To understand how this happens, we need to look at the descriptor protocol.

Descriptor Protocol

Descriptors are the mechanism behind methods, they are objects (classes) that define __get__(), __set__(), or __delete__() methods. To understand how self works, let's just consider __get__(), which has a signature:

descr.__get__(self, instance, type=None) -> value
Copy after login

But what does the __get__() method actually do? It allows us to customize property lookup in a class - or in other words - customize what happens when class properties are accessed using dot notation. This is very useful considering that methods are really just properties of the class. This means we can use the __get__ method to create a "bound method" of a class.

To make it easier to understand, let's demonstrate this by implementing a "method" using a descriptor. First, we create a pure Python implementation of a function object:

import types
class Function:
def __get__(self, instance, objtype=None):
if instance is None:
return self
return types.MethodType(self, instance)
def __call__(self):
return
Copy after login

The Function class above implements __get__ , which makes it a descriptor. This special method receives the class instance in the instance parameter - if this parameter is None, we know that the __get__ method was called directly from a class (e.g. MyClass.do_stuff), so we just return self. However, if it is called from a class instance, such as instance.do_stuff, then we return types.MethodType, which is a way of manually creating a "bound method".

In addition, we also provide the __call__ special method. __init__ is called when a class is called to initialize an instance (e.g. instance = MyClass()), while __call__ is called when an instance is called (e.g. instance()). We need to use this because self in types.MethodType(self, instance) must be callable.

Now that we have our own function implementation, we can use it to bind methods to the class:

class MyClass:
do_stuff = Function()
print(MyClass.__dict__["do_stuff"])# __get__ not invoked
# <__main__.Function object at 0x7f229b046e50>
print(MyClass.do_stuff)# __get__ invoked, but "instance" is None, "self" is returned
print(MyClass.do_stuff.__get__(None, MyClass))
# <__main__.Function object at 0x7f229b046e50>
instance = MyClass()
print(instance.do_stuff)#__get__ invoked and "instance" is not None, "MethodType" is returned
print(instance.do_stuff.__get__(instance, MyClass))
# <bound method ? of <__main__.MyClass object at 0x7fd526a33d30>
Copy after login

By giving MyClass an attribute do_stuff of type Function, we Roughly emulates what Python does when defining methods in a class's namespace.

To sum up, when accessing attributes such as instance.do_stuff, do_stuff is searched in the attribute dictionary (__dict__) of the instance. If do_stuff defines a __get__ method, do_stuff.__get__ is called, ultimately calling:

# For class invocation:
print(MyClass.__dict__['do_stuff'].__get__(None, MyClass))
# <__main__.Function object at 0x7f229b046e50>
# For instance invocation:
print(MyClass.__dict__['do_stuff'].__get__(instance, MyClass))
# Alternatively:
print(type(instance).__dict__['do_stuff'].__get__(instance, type(instance)))
# <bound method ? of <__main__.MyClass object at 0x7fd526a33d30>
Copy after login

As we know now - a bound method will be returned - a callable wrapped around the original function Wrapper whose parameters are preceded by self!

If you want to explore this further, static and class methods can be implemented similarly (https://docs.python.org/3.7/howto/descriptor.html#static-methods-and-class-methods)

Why is self in the method definition?

We now know how it works, but there is a more philosophical question - "Why does it have to appear in the method definition?"

The explicit self method parameter is controversial design choice, but it's one that favors simplicity.

Python self-embodies the "worse is better" design philosophy - described here . The priority of this design concept is "simplicity", which is defined as:

The design must be simple, including implementation and interfaces. It's more important that the implementation is simple than the interface...

This is exactly the case with self - a simple implementation at the expense of the interface, where the method signature doesn't match its invocation.

There are of course more reasons why we should write self explicitly, or why it must be preserved, some of which are described in a blog post by Guido van Rossum (http://neopythonic.blogspot.com/ 2008/10/why-explicit-self-has-to-stay.html), the article responded to a request for its removal.

Python abstracts away a lot of complexity, but in my opinion digging into the low-level details and complexity is extremely valuable for better understanding of how the language works, when things break and advanced troubleshooting/debugging When not enough, it can come in handy.

Also, understanding descriptors can actually be quite practical since they have some use cases. While most of the time you really only need @property descriptors, there are some cases where custom descriptors make sense, such as those in SLQAlchemy or e.g. custom validators.

The above is the detailed content of What is the self parameter in Python?. For more information, please follow other related articles on the PHP Chinese website!

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

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. Have Crossplay?
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

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)

PHP and Python: Code Examples and Comparison PHP and Python: Code Examples and Comparison Apr 15, 2025 am 12:07 AM

PHP and Python have their own advantages and disadvantages, and the choice depends on project needs and personal preferences. 1.PHP is suitable for rapid development and maintenance of large-scale web applications. 2. Python dominates the field of data science and machine learning.

How is the GPU support for PyTorch on CentOS How is the GPU support for PyTorch on CentOS Apr 14, 2025 pm 06:48 PM

Enable PyTorch GPU acceleration on CentOS system requires the installation of CUDA, cuDNN and GPU versions of PyTorch. The following steps will guide you through the process: CUDA and cuDNN installation determine CUDA version compatibility: Use the nvidia-smi command to view the CUDA version supported by your NVIDIA graphics card. For example, your MX450 graphics card may support CUDA11.1 or higher. Download and install CUDAToolkit: Visit the official website of NVIDIACUDAToolkit and download and install the corresponding version according to the highest CUDA version supported by your graphics card. Install cuDNN library:

Python vs. JavaScript: Community, Libraries, and Resources Python vs. JavaScript: Community, Libraries, and Resources Apr 15, 2025 am 12:16 AM

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

Detailed explanation of docker principle Detailed explanation of docker principle Apr 14, 2025 pm 11:57 PM

Docker uses Linux kernel features to provide an efficient and isolated application running environment. Its working principle is as follows: 1. The mirror is used as a read-only template, which contains everything you need to run the application; 2. The Union File System (UnionFS) stacks multiple file systems, only storing the differences, saving space and speeding up; 3. The daemon manages the mirrors and containers, and the client uses them for interaction; 4. Namespaces and cgroups implement container isolation and resource limitations; 5. Multiple network modes support container interconnection. Only by understanding these core concepts can you better utilize Docker.

MiniOpen Centos compatibility MiniOpen Centos compatibility Apr 14, 2025 pm 05:45 PM

MinIO Object Storage: High-performance deployment under CentOS system MinIO is a high-performance, distributed object storage system developed based on the Go language, compatible with AmazonS3. It supports a variety of client languages, including Java, Python, JavaScript, and Go. This article will briefly introduce the installation and compatibility of MinIO on CentOS systems. CentOS version compatibility MinIO has been verified on multiple CentOS versions, including but not limited to: CentOS7.9: Provides a complete installation guide covering cluster configuration, environment preparation, configuration file settings, disk partitioning, and MinI

How to operate distributed training of PyTorch on CentOS How to operate distributed training of PyTorch on CentOS Apr 14, 2025 pm 06:36 PM

PyTorch distributed training on CentOS system requires the following steps: PyTorch installation: The premise is that Python and pip are installed in CentOS system. Depending on your CUDA version, get the appropriate installation command from the PyTorch official website. For CPU-only training, you can use the following command: pipinstalltorchtorchvisiontorchaudio If you need GPU support, make sure that the corresponding version of CUDA and cuDNN are installed and use the corresponding PyTorch version for installation. Distributed environment configuration: Distributed training usually requires multiple machines or single-machine multiple GPUs. Place

How to choose the PyTorch version on CentOS How to choose the PyTorch version on CentOS Apr 14, 2025 pm 06:51 PM

When installing PyTorch on CentOS system, you need to carefully select the appropriate version and consider the following key factors: 1. System environment compatibility: Operating system: It is recommended to use CentOS7 or higher. CUDA and cuDNN:PyTorch version and CUDA version are closely related. For example, PyTorch1.9.0 requires CUDA11.1, while PyTorch2.0.1 requires CUDA11.3. The cuDNN version must also match the CUDA version. Before selecting the PyTorch version, be sure to confirm that compatible CUDA and cuDNN versions have been installed. Python version: PyTorch official branch

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