List of useful suggestions for building Python library APIs

This article is based on a presentation at 2017 PyCon: How to make a good library API. Lists a list of helpful suggestions for building Python library APIs.

Simplicity

Write a simple client code in the README file. For example: Pendulum's README file starts with simple user code.

Reduce redundant code: count the number of lines from the first line to the actual call of the API function. For example: Compared to the Request library, the urllib2 library is a lot of redundant code when making HTTP requests.

Use case example: This page shows content: https://python-social-auth-docs.readthedocs.io/en/latest/use_cases.html

Gradually improve in practice: practical and sensible default settings

- Has default settings and sets defaults based on the most common usage conditions.

- Set the position of the parameters, put the most commonly used parameters in front, and put them together similarly. For example: The default argument order for the history.pushState function of JavaScript is: state, title, URL. However, many users simply want to add URLs to historical values, but the actual situation forces them to set the value of the state and title parameters.

Do not copy and paste source code snippets into your API.

Avoid troublesome input: - Check for ambiguity of parameter names. For example, in Scrapy 1.2, the send method has a to parameter that receives a list of strings. If the user passes in a string, this method will iterate through the string and treat each character as an email address and send an email. In Scrapy 1.3, this bug was modified. After the modification, it can receive a string or receive a list of strings. - Check if you are instantiating something just to call the API. If so, consider receiving the encapsulated value. For example: For a function that only accepts file-like objects, if you want to call it, you have to use the StringIO module. - Check if you can use the built-in type to replace the custom type. Or both support the use.

Principle of least astonishment: If a feature of a function is surprising, it may be worth considering redesigning it. - Does the program default behavior be what the user expects? - Does the program's default behavior meet user requirements for program performance, side effects, security, reliability, security, and restrictions?

To be abstract - let the user do not need to care about how the problem is solved, but care about what to solve. For example: In order to complete a simple job, project developers do not have to worry too much about task sequences, message destruction, serialization, etc. They simply use a decorator such as @aap.task. The focus of the API is on the definition of the task rather than the process of completing the task. - Check if the API contains something that shouldn't be. Remember to be careful about the so-called "The Law of Leaky Abstractions". For example: RPC (remote procedure call) is a good negative teaching material, because it treats remote resources as local resources for abstraction, but in fact remote resources are handled differently than local resources.

Look like Python - try to approach common Python conventions so that your API calls look just like Python's built-in APIs. For example in Python2, ConfigParser.get accepts a section parameter and an option parameter. However, this does not conform to the Python convention. In the Python dictionary (dict) object's get method, we accept the key parameter and a default parameter. In Python 3, this problem was fixed and the function's parameter input was like a dictionary.

consistency

Naming Question: Is the naming in your API consistent with Python conventions? Our naming should be consistent with that given in PEP8. PEP8 is the official code style guide for Python. In order to keep the naming and code style consistent, we recommend using flake8 to standardize your API code.

Naming Question: Is the naming in the API the same? - Order of terms: string_encode VS decode_string - Abbreviations Question: activate_prev VS fetch_previous and bin2hex VS strtolower - Is it underlined: gettype VS get_class - single and plural problem: values_list VS value_list - positive and negative questions: button.enabled == True VS button. Disabled == True

Null problem: Is the definition of null meaning the same? Is the current best choice? - Decide which of the following represents the null value: None, False, [], '', 0 - Beware of some unexpected values: bool(datetime.time(0)) == False

Parameter question: Is there consistency in the order of the parameters? For example: datetime.datetime(year, month, day, minute, second, microsecond) vs datetime.timedelta(days, seconds, microseconds, milliseconds, minutes, hours, weeks)

Behavioral issues: Is there consistency between similar or different behaviors? The asymmetry of behavior should be reflected in the asymmetry of the format. For example, numbers.sort() VS sort(numbers)

flexibility

Reduce overall discontinuity - check if all functions of a class are single responsibility? If not, they should be disassembled. For example, a class that fetches data from the cache should hand over its steps to connect to the cache server to another class.

- Check if the function name contains `and` or if it contains multiple operations. If this is indeed the case, this function should be split into several different functions. However, if this function is called often, it is possible to keep a function that combines many functions. For example: The print_formatted function can be disassembled into two functions: print and formated

- Check if there is a user copy paste code to change the function of the function. Should provide code reconstruction, callback function.

- Check if the property value is used inside the function. If it can use get_something method instead. For example, in Djando's REST framework, the CursorPagination class only supports a fixed-size attribute value: page_size, which is because this class does not have a get_page_size method. This problem was later solved by the above method, that is, the get_page_size method was added.

- Try to avoid hiding potentially useful parameters. For example, our API calls another low-level API but does not show the parameters of this low-level API.

- Return everything the user may need

- The user may need to handle all situations when the user calls the API

- Each mock.pathch is tested during API testing. Although some things are not easy to modify when the program is running, we can modify something by setting parameters. For example, Python's built-in function sched.scheduler accepts two parameters timefunc and delayfunc. However, we do not need to mock test the time.monotonic and time.sleep functions. The user will make corresponding changes according to their own needs.

Build abstractions - In accordance with the structure of the underlying implementation, we encapsulate our function members and objects. For example, Beautiful Soup has designed the same API structure for multiple analyzers.

- Provide a multi-level abstract structure, from the simplest to the most personalized. For example, Celery provides both a @app.task decorator and a personalized task class that inherits from celery.Task

- Provides a way to get rid of the package, allowing users to use abstracted resources and capabilities directly. For example, Django's query collection supports the use of the .extra method to combine custom SQL with ORM to generate query statements. It also supports the use of .raw to directly use native SQL query statements.

- Encapsulate common errors in the underlying implementation to avoid giving users direct error. For example, when the API supports multiple data engines, when the database connection error occurs, the displayed information should be the same. This helps the user to find out where the problem is, and does not need to modify a lot of code when modifying the database engine.

To have Python scope - Use Python's native properties for get and set operations - Use magic methods for operator overloads - For simple debugging, use the __repr__ magic method - For inclusion - Shut down or start-end such problems with lifecycles, use with-statements - use decorators for easily combining common behaviors or registering something - use iterators for iterations - use generators for complex logic problems - use for asynchronous problems Asyncio - Use built-in collections whenever possible - Use simple high-level functions for simple control inversion, such as accepting the key parameter as a level high and low calculation function in the list.sort function to calculate the order of the list. - For complicated process problems, you can think about them in the order of function/class pipeline, inheritance, and generator. For example, the pipeline problem may refer to: python-social-auth pipeline; inheritance issues may refer to: Django's classes; generator problems may refer to: Scrapy's crawler. - Respect Duck-style programming style and require understanding is easier than understanding itself

The string that internationalized end users see.

safety

Examine the warning words in the documentation that describe the function of the function, for example: warning, careful, remember to, dont't forget. If these words exist, you have to consider how to change the code to make the function more secure and stable.

Check for common errors and use Python's built-in warning module to log warnings

Clearly unsafe behavior. For example, if some variables do not have set values, don't set them specifically. Do not write statements like filesds = None everywhere.

Do not implicitly link code by object name or module name, use a registration function, or register a decorator. For example, Django-admin's registration problem not only supports passing functions but also supports decorators.

Do not rely on the calling order of methods. Use the with statement as much as possible.

Quick error: It's not Python-style thinking to exit directly if something goes wrong.

- When a library function receives an invalid parameter with an incorrect format or an incorrect expression, such as a parameter overflow, a Value Error error is generated. - A TypeError error occurs when a library function receives an incompatible type of data. For example, the duck type is not compatible with the quack type. Do not throw an exception in a statement such as if isinstance(duck, LibDuck) or if type(duck) == LibDuck). First try using quack, throwing a TypeError exception if an error occurs and printing a clear error message.

Summary My API aims to simplify simple things, turn complicated things into reality, and eliminate the wrong things forever.

Budget Gaming Laptop

15.6 inch i5 5th Budget Gaming Laptop in plastic is more competitive one in device in 2022, only need around 300usd. However, 15.6 inch 500 dollar gaming laptops is one of the most important top 10 budget gaming laptops, like 14 inch i7 budget gaming laptop under 500, 15.6 inch 11th 512gb laptop, etc.

However, top budget gaming laptops also have other levels, like 15.6 inch i5 laptop 10th generation, 15.6 inch 11th generation laptop i7 512gb, etc. 2022 top laptops under 500 with 14 inch i3 i5 i7 10th you can see here also.

The custom laptop is also of updated, quality hardware, big battery, rich slots, charging by Type C, etc.

Nowadays, the hardware and mature of custom laptop is nearly no difference with brand one, so pls believe you can get a satisfy laptop for your special project, like students project, office project, gaming club etc.

Except laptop, also have custom Android Tablet, Mini PC , All In One PC, 2 In 1 Laptop, also availble.


Any other specail demand, you can contact us and share your requirements details, then matched details sended quickly.

Budget Gaming Laptop,Budget Gaming Laptop Under 500,Top Budget Gaming Laptops,Top Laptops Under 500,Top 10 Budget Gaming Laptops

Henan Shuyi Electronics Co., Ltd. , https://www.shuyioemelectronics.com