Python Approval Style

I am wondering if what I am doing is a suitable method of statements. I am trying to do something short and very correct for Python style guides.

try: assert self.port_number == 0 assert self.handle == None assert isinstance(port_number, int) or isinstance(port_number, float) assert port_number > 0 except AssertionError: return -1 *body of code* return 0 

Above is an excerpt from my code that shows how I handle arguments. You can assume that I have considered all the necessary statements, and input is port_number. Is this considered a good style? Is there a better way?

+4
source share
4 answers

If the calling function expects input 0 on success and -1 on failure, I would write:

 def prepare_for_connection(*args, **kwargs): if (self.handle is not None): return -1 if not (isinstance(port_number, int) or isinstance(port_number, float)): return -1 if port_number < 0: return -1 # function body return 0 

The challenge to the metadata mechanism and catching assertion errors for non-exclusive behavior is too great. Statements are better for cases where the operator must always be true, but if it is not due to some error, you loudly generate an error in this place or, at best, process it (with the default value) in this place. You can combine conditional expressions with multiple-ifs into one giant conditional statement if you want; I personally find this more readable. In addition, python style should be compared to None using is and is not , not == and != .

Python should be able to optimize statements when a program leaves the debug phase. See http://wiki.python.org/moin/UsingAssertionsEffectively

Provided that this convention of returning the error number (-1/0) from the C-style is not particularly python. I would replace -1 with False and 0 with True and give it a semantically meaningful name; for example, call it connection_prepared = prepare_for_connection(*args,**kwargs) , so connection_prepared will be True or False , and the code will be very readable.

 connection_prepared = prepare_for_connection(*args,**kwargs) if connection_prepared: do_something() else: do_something_else() 
+2
source

The assert should only be used to check the internal logic of the program, never check the user input or environment. Quote from the last two paragraphs at http://wiki.python.org/moin/UsingAssertionsEffectively ...

Claims should not be used to check for crashes that might occur due to bad user input or the operating system / crash environment, such as a file that was not found. Instead, you should raise an exception, or print an error message or something suitable. One important reason that statements should only be used for self-testing of a program is because statements can be disabled at compile time.

If Python is run with the -O option, then the statements will be denied and not evaluated. Therefore, if the code makes heavy use of statements, but is critical for performance, then there is a system for turning them off. in releases. (But do not do this if it is really necessary. It has been scientifically proven that some errors appear only when the client uses the machine, and we want the statements to help there too.)

With this in mind, there is almost never any reason to assert the statement in the user code, since the entire statement point is not required to notify the programmer as soon as possible that the program has a logical error.

+5
source

I prefer not to catch the statement inside the function, but instead make sure that the caller handles any errors. It also allows the caller to check for any unhandled errors and check the trace to see exactly what went wrong.

You can also add an error message to your claims.

 assert x > 0, "x must be greater than 0" 
+3
source
 return -1 

Python has a different error handling method than C. If there is a problem with the data provided, simply allow the AssertionError to pass or raise a TypeError or ValueError with a special error message. A custom error message with assert statement is the simplest:

 assert port_number > 0, "Invalid port number" 

The fact that assert statements may be disabled at compile time may be a point to consider if you want to use assert statements in your situation. It’s not common practice to use assert statements to validate user input for your functions, but only for internal sanity checks. On the other hand, the boundaries between sanity checks and validation are not defined. Examples of parts of your code without claims:

 if port_number <= 0: raise ValueError('Invalid port number') if not isinstance(port_number, (int, float)): raise TypeError('Port number must be some kind of number') 

Personally, I use assert statements to verify data that, if invalid, will fail sooner or later in any case (see "duck print"). I also actively use assertions during development to verify performance - I check my data, as it would in a statically typed language. I use only such statements if I strongly doubt the stability and reliability of my own code.

Next line:

 assert self.handle == None 

If I remember correctly, PEP8 says you should write assert self.handle is None . At least it was approved by people who are smarter than me.

 assert isinstance(port_number, int) or isinstance(port_number, float) 

If you really need it, it can be written as isinstance(port_number, (int, float)) . But it turns out you won’t do it. You don’t care if anyone passes a numerical primitive type or some kind of makeshift class that overloads all comparison operators.

Perhaps one thing you can do is try to pass the port to an integer and see if it can be used or not:

 try: port_number = int(port_number) except ValueError: raise ValueError("Invalid port number") 

And also in this case, you can simply skip ValueError , the message will be less informative for beginners.

+1
source

Source: https://habr.com/ru/post/1490328/


All Articles