Up to now, we have covered the introduction you will use most of the aspects of Python. In this chapter, we will introduce some other aspects, to make us a more comprehensive understanding of Python.
1. The transfer-tuple
Did you ever want to return two different values from a function? You can do it. Only you need to use a tuple.
>>> def get_error_details():
... return (2, 'details')
...
>>> errnum, errstr = get_error_details()
>>> errnum
2
>>> errstr
'details'
To note a, b = <some expression>
the results of the use of the expression it will be interpreted as a tuple with two values.
This also means that the fastest way to swap two variables in Python is:
>>> a = 5; b = 8
>>> a, b
(5, 8)
>>> a, b = b, a
>>> a, b
(8, 5)
2. Special method
Such as __init__
and __del__
some of the methods that have special meaning for the class is.
The method used to simulate the behavior of certain special built-in types. For example, if you want to use for your class x[key]
indexing operations (just like you use in the list and tuple), then you need to do is just realize __getitem__()
method, then your work is done. If you try to understand it, it is to think about the Python list
class to do so!
The following table lists some useful special methods. If you want to know all the special methods, please refer to the manual .
__init__(self, ...)
- This method is called when the newly created object is returned ready to use.
__del__(self)
- This method is invoked before the object is deleted (the timing of its use unpredictable, so avoid using it)
__str__(self)
- When we use
print
a function, orstr()
will be called upon to be used.
- When we use
__lt__(self, other)
- When less than when the operator (<) is used to be called. Similarly, all the other operators (+,>, etc.) have a specific method is called.
__getitem__(self, key)
- Use
x[key]
will be called when the index operation.
- Use
__len__(self)
- When using the built-in objects for the sequence
len()
when the function is called.
- When using the built-in objects for the sequence
3. Single statement block
We've seen each block of statements by its own indentation level with the rest of distinguished. This is true, but there is a small warning. If you block of statements includes only a single statement, then you can specify it in the same row, for example, conditional statements and loop statements. The following example should be able to more clearly explain:
>>> flag = True
>>> if flag: print('Yes')
...
Yes
Note that a single statement is used in place immediately, it will not be regarded as a single block. Although, you can make your program this way is more compact , but unless it is to check for errors, I highly recommend that you avoid using this shortcut method, mainly because if you accidentally used a "just right" shrink Jin, it is very easy to add additional statements.
4. Lambda table
lambda
Statement creates a new function object. In essence, lambda
requires an argument, followed by an expression as a function of the body, the value of this expression will be executed as the return value of new functions.
Case (save as more_lambda.py
):
points = [{'x': 2, 'y': 3},
{'x': 4, 'y': 1}]
points.sort(key=lambda i: i['y'])
print(points)
Output:
$ python more_lambda.py
[{'y': 1, 'x': 4}, {'y': 3, 'x': 2}]
To a notice list
of sort
ways to get a key
parameter to determine the ordering of the list (usually we only know ascending and descending). In our case, we want to conduct a custom sorting, for which we need to write a function, but it is not written as a separate function def
blocks, only in this one place, so we use Lambda expressions to create a new function.
5. Derivation list
List comprehension (List Comprehension) to get a new list from an existing list. Imagine, now you've got a list of numbers, you want to get a corresponding list, which numbers in the case of more than 2 will be multiplied by two. List comprehension is ideal for such situations.
Case (save as more_list_comprehension.py
):
listone = [2, 3, 4]
listtwo = [2*i for i in listone if i > 2]
print(listtwo)
Output:
$ python more_list_comprehension.py
[6, 8]
In this case, when certain conditions are met ( if i > 2
), we specified operation ( 2*i
), in order to get a new list. To note that the original list remains unchanged.
The advantage of using a list of derived that when we use a loop to process each element in the list and stores the new list from time to time, it reduces the number of template (Boilerplate) code.
6. Receive tuples dictionary function
One particular method that were used *
or **
prefix tuple or dictionary, to make them function as a parameter is received. When the function requires a variable number of arguments, which will be quite helpful.
>>> def powersum(power, *args):
... '''Return the sum of each argument raised to the specified power.'''
... total = 0
... for i in args:
... total += pow(i, power)
... return total
...
>>> powersum(2, 3, 4)
25
>>> powersum(2, 10)
100
Because we args
added a variable before *
prefix, all other additional parameters are passed to the function args
in, and as a tuple to be stored. If a **
prefix, the additional parameters will be treated as a dictionary key - value pairs.
7. assert
Statement
assert
Statement to the assertion (Assert) that something is true. For example say you are very sure you are using the list contains at least one element, and want to make sure that, if it is not true, it throws an error, assert
the statement is ideal in this case. When a statement is an assertion fails, it will be thrown AssertionError
.
>>> mylist = ['item']
>>> assert len(mylist) >= 1
>>> mylist.pop()
'item'
>>> assert len(mylist) >= 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
You should choose wisely assert
statement. In most cases, it is better to catch the exception, better than the positioning problem or display an error message to the user and then exit.
8. decorator
Decorator (Decorators) is a shortcut to the application wrapper function. This helps to a certain function with some code over and over again, "packaging." For example, I created for myself a retry
decorator, so that I can be applied to any function within, If you throw any errors in a single run, it will try to re-run until the maximum number of five times, and there will be some delays during each run. This is very useful when you are on a remote computer network call:
from time import sleep
from functools import wraps
import logging
logging.basicConfig()
log = logging.getLogger("retry")
def retry(f):
@wraps(f)
def wrapped_f(*args, **kwargs):
MAX_ATTEMPTS = 5
for attempt in range(1, MAX_ATTEMPTS + 1):
try:
return f(*args, **kwargs)
except:
log.exception("Attempt %s/%s failed : %s",
attempt,
MAX_ATTEMPTS,
(args, kwargs))
sleep(10 * attempt)
log.critical("All %s attempts failed : %s",
MAX_ATTEMPTS,
(args, kwargs))
return wrapped_f
counter = 0
@retry
def save_to_database(arg):
print("Write to a database or make a network call or etc.")
print("This will be automatically retried if exception is thrown.")
global counter
counter += 1
# 这将在第一次调用时抛出异常
# 在第二次运行时将正常工作(也就是重试)
if counter < 2:
raise ValueError(arg)
if __name__ == '__main__':
save_to_database("Some bad value")
Output:
$ python more_decorator.py
Write to a database or make a network call or etc.
This will be automatically retried if exception is thrown.
ERROR:retry:Attempt 1/5 failed : (('Some bad value',), {})
Traceback (most recent call last):
File "more_decorator.py", line 14, in wrapped_f
return f(*args, **kwargs)
File "more_decorator.py", line 39, in save_to_database
raise ValueError(arg)
ValueError: Some bad value
Write to a database or make a network call or etc.
This will be automatically retried if exception is thrown.
to sum up
We introduced more features about Python in this chapter, but we have not covered all the features of the Python. However, at this stage, we have covered most of what you will encounter in practice. This is enough to get you started writing any of your desired program.
Next, we will discuss how to further explore Python.