In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces the example analysis of Python programming application design principles, the article is very detailed, has a certain reference value, interested friends must read it!
1. Single responsibility principle SRP
The English description of the single responsibility principle (Single Responsibility Principle) is as follows: A class or module should have a single responsibility. If we translate it into Chinese, it is that a class or module is only responsible for performing one duty (or function).
Let's take a simpler example, we have a number L = [N1, N2, … , nx], we calculate some mathematical functions. For example, calculate the maximum, average, and so on.
A bad way is to let a function do all the work:
Import numpy as np def math_operations (list_): # Compute Average print (f "the mean is {np.mean (list_)}") # Compute Max print (f "the max is {np.max (list_)}") math_operations (list_ = [1, 2, 3, 4, 5]) # the mean is, 3, 4, the max is 5
In actual development, you can think of math_operations as huge, mixed with all kinds of functional code.
To make this more consistent with the single responsibility principle, the first thing we should do is to split the function math_operations into finer-grained functions that do only one thing:
Def get_mean (list_):''Compute Max''' print (f "the mean is {np.mean (list_)}") def get_max (list_):' 'Compute Max''' print (f "the max is {np.max (list_)}") def main (list_): # Compute Average get_mean (list_) # Compute Max get_max (list_) main 5]) # the mean is 3. The max is 5
The benefits of this are:
Easy to read and debug, easier to locate errors.
Reusable, any part of the code can be reused in other parts of the code.
Testable, making it easier to create tests for each function of the code.
But to add new features, such as calculating median, the main function is still difficult to maintain, so you need a second principle: OCP.
2. Open and close principle OCP
The opening and closing principle (Open Closed Principle) is open to extension and closed to modification, which can greatly improve the maintainability of the code, that is to say, when you want to add new features, you only need to add new code without modifying the original code, which is simple and will not affect the previous unit test. It is not easy to make mistakes, and you only need to check the newly added code even if something goes wrong.
The above code can solve this problem by turning all the functions we write into subclasses of a class. The code is as follows:
Import numpy as npfrom abc import ABC Abstractmethodclass Operations (ABC):''Operations''' @ abstractmethod def operation (): passclass Mean (Operations):' 'Compute Max''' def operation (list_): print (f "The mean is {np.mean (list_)}") class Max (Operations):' 'Compute Max''' def operation (list_): print (f "The max is {np.max (list_)) } ") class Main:''Main''' def get_operations (list_): # _ _ subclasses__ will found all classes inheriting from Operations for operation in Operations.__subclasses__ (): operation.operation (list_) if _ _ name__ = =" _ _ main__ ": Main.get_operations ([1mem2 3, The mean is, 4, 5]) # The mean is, 3, 5, 5
If we want to add a new operation now, such as median, we just need to add a Median class that inherits from the Operations class. The newly formed subclass is immediately received by _ _ subclasses__ () without any modification to any other part of the code.
3. Richter substitution principle (LSP)
The principle of interior substitution is Liskov Substitution Principle in English and abbreviated as LSP. This principle was first proposed by Barbara Liskov in 1986, and this is how he described it:
If S is a subtype of T, then objects of type T may be replaced with objects of type S, without breaking the program .
In other words, the subclass object can replace wherever the parent object appears in the program, and ensure that the logical behavior and correctness of the original program remain unchanged.
In fact, there is another more landing and instructive description of the inner substitution principle, which is designed according to the protocol, and the subclass should abide by the behavior agreement (or protocol) of the parent class when designing. The parent class defines the behavior convention of the function, and that subclass can change the internal implementation logic of the function, but cannot change the original behavior convention of the function. The behavior conventions here include: the function declares the functions to be implemented; the conventions for inputs, outputs, and exceptions; and even any special instructions listed in the comments.
4. Interface isolation principle (ISP)
The English translation of the principle of interface isolation is Interface Segregation Principle, abbreviated as ISP. Robert Martin defines it like this in the SOLID principle: Clients should not be forced to depend upon interfaces that they do not use.
The client should not be forced to rely on interfaces it does not need. The client can be understood as the caller or user of the interface.
For example:
From abc import ABC Abstractmethodclass Mammals (ABC): @ abstractmethod def swim (self)-> bool: pass @ abstractmethod def walk (self)-> bool: passclass Human (Mammals): def swim (self)-> bool: print ("Humans can swim") return True def walk (self)-> bool: print ("Humans can walk") return True class Whale (Mammals): def walk Self)-> bool: print ("Whales can't walk") return False def swim (self): print ("Whales can swim") return True human = Human () human.swim () human.walk () whale = Whale () whale.swim () whale.walk ()
Execution result:
Humans can swim
Humans can walk
Whales can swim
Whales can't walk
In fact, the subclass whale should not rely on the interface walk it does not need. In this case, you need to split the interface as follows:
From abc import ABC, abstractmethodclass Swimer (ABC): @ abstractmethod def swim (self)-> bool: passclass Walker (ABC): @ abstractmethod def walk (self)-> bool: passclass Human (Swimer) Walker): def swim (self)-> bool: print ("Humans can swim") return True def walk (self)-> bool: print ("Humans can walk") return Trueclass Whale (Swimer): def swim (self): print ("Whales can swim") return Truehuman = Human () human.swim () human.walk () whale = Whale () whale.swim () 5, dependency inversion principle (DIP)
The English translation that relies on the reversal principle is Dependency Inversion Principle, abbreviated as DIP. English description: High-level modules shouldn't depend on low-level modules. Both modules should depend on abstractions. In addition, abstractions shouldn't depend on details. Details depend on abstractions .
We translate it into Chinese, which roughly means: the high-level module should not rely on the lower-level module. High-level modules and low-level modules should depend on each other through abstractions. In addition, abstraction does not rely on specific implementation details, which depend on abstraction.
In the call chain, the caller belongs to the high level, the callee belongs to the low level, and the code we write belongs to the low level, which is called by the framework. In the usual business code development, there is no problem for the high-level module to rely on the low-level module, but when designing at the framework level, we should consider the versatility, the high level should rely on the abstract interface, and the low-level should implement the corresponding interface. As shown in the following figure:
That is to say, ObjectA originally depends on ObjectB, but in order to extend it, there may be ObjectC,ObjectD, which changes frequently, so in order to change frequently, let the high-level module rely on the abstract interface interface, and then let ObjectB also rely on interface, which is the principle of dependency inversion.
For example, wsgi protocol is an abstract interface, high-level modules such as uWSGI,gunicorn, low-level modules such as Django,Flask, uWSGI,gunicorn does not directly rely on Django,Flask, but through the wsgi protocol for interdependence.
The concept of dependency inversion principle is that high-level modules do not depend on low-level modules. It seems to be requiring high-level modules, but it is actually standardizing the design of low-level modules. The interfaces provided by low-level modules should be abstract and universal enough, and the types and scenarios of high-level modules need to be considered in the design. Obviously, the high-level module uses the low-level module, which is dependent on the low-level module. Now, on the contrary, low-level modules need to be designed according to high-level modules, resulting in the appearance of "inversion".
There are two advantages to this design:
Low-level modules are more universal and have wider applicability.
High-level modules do not rely on the specific implementation of low-level modules, which facilitates the replacement of low-level modules.
The above is all the contents of the article "sample Analysis of Python programming Application Design principles". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!
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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.