Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the best practices applied when defining classes in the advanced version of Python

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article focuses on "what are the best practices applied when defining classes in the advanced version of Python". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "what are the best practices to apply when defining classes in the advanced version of Python?"

As an OOP language, Python processes data and functions by supporting a variety of object-oriented functions. For example, the data structure is all objects, including primitive types (such as integers and strings), while in some other languages, primitive types are not considered objects. For another instance, functions are all objects that simply define the properties of other objects (such as classes or modules).

Although you can use built-in data types and write a set of functions without creating any custom classes, the code may become more and more difficult to maintain as the scope of the project expands. The themes of these individual code sections are different, and although a lot of information is relevant, it is not easy to manage the connections between them.

In these cases, it makes sense to define your own classes so that you can group relevant information and improve the structural design of the project. And because you are about to deal with less segmented code, the long-term maintainability of the code base will be improved. Note, however, that operations can be implemented only when class declarations are completed in the right way, and that the benefits of defining custom classes outweigh the expense of managing them.

1. Okay, name it.

Defining your own class is like adding a new member to the code library. So you should give the class a good name. Although the only restriction on class names is the rule for legal Python variables (for example, you cannot start with a number), there are some useful ways to name a class.

Use nouns that are easy to pronounce. This is especially important when working on a team project. In the group presentation, you probably don't want to say, "in this case, we create an instance of the Zgnehst class." In addition, easy pronunciation also means that the name should not be too long, and it is almost inconceivable to use more than three words to define the class name. One word is the best, two words is second, three words can not be more!

Reflect its stored data and expected functions. Just like in real life-when we see a masculine name, we acquiesce that the child is a boy. The same applies to class names (or any other variable in general), and the naming rules are simple-- don't feel weird. If you want to deal with student information, then the course should be named Student,KiddosAtCampus, which is not a conventional good name.

Follow the naming convention. You should use camel spelling for class names, such as GoodName. The following is an incomplete list of unconventional class names: goodName,Good_Name,good_name and GOodnAme. The naming convention is followed to make the intention clear. When others read your code, there is no doubt that the object named GoodName is a class.

There are also naming rules and conventions for attributes and functions, which are briefly mentioned in the following sections, but the overall principle is the same.

two。 Explicit instance properties

In most cases, we want to define our own instance initialization method (that is, _ _ init__). In this method, the initial state of the newly created class instance is set. However, Python has no restrictions on where you can use custom classes to define instance properties. In other words, you can define other instance properties in subsequent operations after the instance is created.

ClassStudent: def__init__ (self, first_name Last_name): self.first_name = first_name self.last_name = last_name defverify_registration_status (self): status = self.get_status () self.status_verified = status = = "registered" defget_guardian_name (self): self.guardian = "Goodman" defget_status (self): # get the registration status from a database status = query_database (self.first_name Self.last_name) return status

(1) initialization method

As shown above, you can create an instance of the Student class by specifying the first and last name of the student. Later, when the instance method (that is, verify_registration_status) is called, the status property of the Student instance is set.

But this is not an ideal pattern, because if various instance properties are scattered throughout the class, the class will not be able to know what data the instance object has. Therefore, it is a best practice to put the properties of the instance in the _ _ init__ method so that the code reader can understand the data structure of your class from a single location, as shown below:

ClassStudent: def__init__ (self, first_name, last_name): self.first_name = first_name self.last_name = last_name self.status_verified = None self.guardian = None

(2) better initialization method

For problems with instance properties that cannot be set initially, you can set them with placeholder values such as None. Although there is nothing to worry about, this change also helps prevent possible errors that lead to AttributeError ('Student' object has noattribute' status_verified') when you forget to call some instance methods to set the applicable instance properties.

In terms of naming conventions, you should use lowercase letters to name attributes and follow serpentine naming-if you use multiple words, use an underscore to connect them. In addition, all names should have meaningful indications to the data they store (for example, first_name is better than fn).

3. Use attributes; but be concise

Some people learn Python coding with a background in other OOP languages, such as Java, and are used to creating getter and setter for the properties of the instance. You can mimic this pattern by using attribute decorators in Python. The following code shows the basic form of implementing getter and setter using the property decorator:

ClassStudent: def__init__ (self, first_name Last_name): self.first_name = first_name self.last_name = last_name @ property defname (self): print ("Getter for the name") returnf "{self.first_name} {self.last_name}" @ name.setter defname (self) Name): print ("Setter for the name") self.first_name, self.last_name = name.split ()

(3) attribute decoration

After this property is created, although it is implemented through an internal function, we can still use point symbols as a general attribute.

Student = Student ("John", "Smith"). Print ("StudentName:", student.name)... Student.name = "JohnnySmith"... Print ("Aftersetting:", student.name)... Getterfor the name StudentName: JohnSmith Setterfor the name Getterfor the name

(4) use attributes

The advantages of using property implementations include verifying the correct value settings (checking whether strings are used instead of integers) and read-only access (by not implementing the setter method). But you should use attributes at the same time, and if the custom class looks like this, it can be very distracting-- there are too many attributes!

ClassStudent: def__init__ (self, first_name Last_name): self._first_name = first_name self._last_name = last_name @ property deffirst_name (self): return self._first_name @ property deflast_name (self): return self._last_name @ property defname (self): returnf "{self._first_name} {self._last_name}"

(5) abuse attribute

In most cases, these properties can be replaced with instance properties, so we can access them and set them directly. Unless there is a specific need for the benefits of using the above attributes (for example, value validation), using attributes takes precedence over creating attributes in Python.

4. Define a meaningful string representation

In Python, a function with a double underscore before and after its name is called a special or magic method, and some people call it a dunder method. These methods have special uses for the basic operation of the interpreter, including the _ _ init__ method we introduced earlier. Two special methods, _ _ repr__ and _ _ str__, are critical to creating the correct string representation of a custom class, which will provide code readers with more intuitive information about the class.

The main difference between them is that the _ _ repr__ method defines a string that you can use to recreate the object by calling eval (repr ("therepr")), while the string defined by the _ _ str__ method is more descriptive and allows for more customization. In other words, you can assume that the string defined in the _ _ repr__ method is viewed by the developer, while the string used in the _ _ str__ method is viewed by the regular user. Look at the following example:

ClassStudent: def__init__ (self, first_name, last_name): self.first_name = first_name self.last_name = last_name def__repr__ (self): returnf "Student ({self.firstroomnameroomr}) {self.lastroomnametellr}) "def__str__ (self): returnf" Student: {self.first_name} {self.last_name} "

Implementation of string representation:

Note that in the implementation of the _ _ repr__ method, the f string uses! r to display these strings in quotes, because it is necessary to construct an instance with a well-formed string. If the! r format is not used, the string will be Student (John, Smith), which is not the correct way to construct a "student" instance.

Let's see how these implementations display strings for us: the _ _ repr__ method is called when the object is accessed in the interactive interpreter, and the _ _ str__ method is called by default when the object is printed.

> student = Student ("David", "Johnson") > student Student ('David',' Johnson') > print (student) Student: DavidJohnson

String representation

5. Instance methods, class methods, and static methods

In a class, we can define three methods: instance methods, class methods, and static methods. We need to consider which methods should be used for the functions we are concerned about. Here are some general guidelines.

For example, if the method is related to a single instance object, you need to access or update the specific properties of the instance. In this case, the instance method should be used. These methods have the following signature: def do_something (self):, where the self argument references the instance object that called the method.

If the method is independent of a single instance object, you should consider using class methods or static methods. You can easily define these two methods using applicable modifiers: class methods (classmethod) and static methods (staticmethod).

The difference between the two is that class methods allow you to access or update properties related to the class, while static methods are independent of any instance or class itself. A common example of a class method is to provide a convenient instantiation method, while a static method can be just a utility function. Look at the following code example:

ClassStudent: def__init__ (self,first_name, last_name): self.first_name = first_name self.last_name = last_name defbegin_study (self): print (f "{self.first_name} {self.last_name} beginsstudying.") @ classmethod deffrom_dict (cls) Name_info): first_name = name_info ['first_name'] last_name = name_info [' last_name'] returncls (first_name,last_name) @ staticmethod defshow_duties (): return "Study,Play, Sleep"

Different methods

Class properties can be created in a similar way. Unlike the instance properties discussed earlier, class properties are shared by all instance objects, and they should reflect some characteristics independent of each instance object.

6. Encapsulated with private attributes

When writing custom classes for your project, you need to consider encapsulation, especially if you expect others to use your class as well. As the functionality of a class grows, some functions or attributes are only relevant to data processing within the class. In other words, none of these functions will be called except for the class, and the users who use the class except you won't even care about the implementation details of these functions. In these cases, encapsulation should be considered.

By convention, an important way to apply encapsulation is to underscore or underscore properties and functions. There is a slight difference between the two: those with underscores are considered protected, while those with two underscores are considered private, which involves name processing after creation.

In essence, naming attributes and functions like this tells IDE (that is, the integrated development environment, such as PyCharm) that although there are no truly private attributes in Python, they will not be accessed outside the class.

ClassStudent: def__init__ (self,first_name, last_name): self.first_name = first_name self.last_name = last_name defbegin_study (self): print (f "{self.first_name} {self.last_name} beginsstudying.") @ classmethod deffrom_dict (cls) Name_info): first_name = name_info ['first_name'] last_name = name_info [' last_name'] returncls (first_name,last_name) @ staticmethod defshow_duties (): return "Study,Play, Sleep"

Encapsulation

The above code shows a simple example of encapsulation. If we want to know the students' evaluation of GPA, we can use the get_mean_gpa method to get the GPA. Users do not need to know how the average GPA is calculated, we can protect the method by adding an underscore before the function name.

The main benefit of this best practice is that only the minimum number of public API related to users' use of your code is disclosed. For code that is used internally only, set it to a protected or private method.

7. Separation of concerns and decoupling

As the project evolves, you will find yourself working with more data, and it will be troublesome if you stick to only one class. Continue to take the "student" category as an example, suppose that students eat lunch at school, and everyone has a catering account that can be used to pay for meals. In theory, we can handle account-related data and functions in the student class, as follows:

ClassStudent: def__init__ (self, first_name, last_name Student_id): self.first_name = first_name self.last_name = last_name self.student_id = student_id defcheck_account_balance (self): account_number = get_account_number (self.student_id) balance = get_balance (account_number) return balance Defload_money (self Amount): account_number = get_account_number (self.student_id) balance = get_balance (account_number) balance + = amount update_balance (account_number, balance)

Mixed function

The above code shows some pseudo code about checking account balances and recharging accounts, both of which are implemented in the Student class. There are more operations related to the account, such as freezing lost cards and merging accounts-all of which make the "student" class larger and larger, making maintenance more and more difficult. You should separate these responsibilities and make the student class not responsible for these account-related functions, a design pattern called decoupling.

ClassStudent: def__init__ (self, first_name, last_name Student_id): self.first_name = first_name self.last_name = last_name self.student_id = student_id self.account = Account (self.student_id) defcheck_account_balance (self): return self.account.get_balance () defload_money (self Amount): self.account.load_money (amount) classAccount: def__init__ (self, student_id): self.student_id = student_id # get additional information from the database self.balance = 400defget_balance (self): # Theoretically, student.account.balance will work But just in case # we need to have additional steps to check, such as query the database # again to make sure the data is up to date return self.balance defload_money (self, amount): # get the balance from the database self.balance + = amount self.save_to_database ()

Separate concerns

The above code shows how we can use additional Account classes to design data structures. As you can see, we move all account-related operations to the Account class. To achieve the function of retrieving the student's account information, the student class will process it by retrieving the information from the Account class. If you want to implement more functionality related to this class, simply update the Account class.

The main point of the design pattern is that you want each class to have a separate focus. By separating these responsibilities, your classes will become smaller, and dealing with smaller code components will make future changes easier.

8. Consider using _ _ slots__ for optimization

If your class is mainly used as a data container for storing data, consider using _ _ slots__ to optimize the performance of your class. It not only improves the speed of property access, but also saves memory, which is where it plays a big role if you need to create thousands or more instance objects.

The reason is that, for regular classes, instance properties are stored through an internally managed dictionary. By contrast, using the _ _ slots__, instance property uses the array-related data structures implemented behind the scenes in C, and optimizes their performance more efficiently.

ClassStudentRegular: def__init__ (self,first_name, last_name): self.first_name = first_name self.last_name = last_name classStudentSlot: _ _ slots__ = ['first_name',' last_name'] def__init__ (self,first_name Last_name): self.first_name = first_name self.last_name = last_name

Use _ _ slots__ in the definition of a class

The above code shows a simple example of how to implement _ _ slots__ in a class. Specifically, listing all attributes as a sequence creates an one-to-one match in the data store to speed up access and reduce memory consumption. As mentioned earlier, regular classes use dictionaries for attribute access, but do not use dictionaries that implement _ _ slots__. The following code confirms this:

> student_r = StudentRegular ('John',' Smith') > student_r.__dict__ {'first_name':' John', 'last_name':' Smith'} > student_s = StudentSlot ('John') 'Smith') > student_s.__dict__ Traceback (most recentcall last): File "", line 1, in AttributeError:' StudentSlot' object has noattribute'_ _ dict__'

There is no _ _ slots__ in the class with _ _ dict__

A detailed discussion of using _ _ slots__ can be found at Stack Overflow, or you can find more information in the official documentation (https://docs.python.org/3/reference/datamodel.html)).

It is important to note that using _ _ slots__ has a side effect-it prevents you from dynamically creating other properties. It has been suggested as a mechanism to control the properties owned by a class, but this is not what it was designed to do.

9. File

Finally, we must discuss the documentation of the class. We need to understand that writing documentation is no substitute for any code, and that writing a large number of documents does not improve the performance of the code, nor does it necessarily make the code more readable. If you have to rely on documentation strings to clarify your code, there is likely to be something wrong with your code.

The following code shows you a mistake a programmer can make-code that uses unnecessary comments to compensate for the error (that is, in this case, a meaningless variable name). By contrast, some good code with good names doesn't even need comments.

# how many billable hours a = 6 # the hourly rate b = 100 # total charge c = a * b # The above vs.the below with no comments billable_hours = 6 hourly_rate = 100 total_charge = billable_hours * hourly_rate

Failure interpretation case

I'm not saying that I'm against writing comments and document strings, which really depends on my own example. If your code is used by multiple people or multiple times (for example, you are the only one who accesses the same code multiple times), then you should consider writing some good comments.

These comments can help you or your team partners read your code, but they can't assume that your code completely follows the instructions in the comments. In other words, writing good code is always the top priority to keep in mind.

If end users want to use specific parts of the code, they need to write documentation strings because these people are not familiar with the relevant code base. They just want to know how to use the relevant API, and the document string will form the basis of the help menu. Therefore, as a programmer, it is your responsibility to make sure that you provide clear instructions on how to use the program.

At this point, I believe that you have a deeper understanding of "what are the best practices applied when defining classes in the advanced version of Python?" you might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report