The Interest And Usefulness Review Of Python 3 Part 1

The Interest And Usefulness Review Of Python 3 Main Logo

The Interest And Usefulness Review Of Python 3 Part 1

I’ve been programming python for several years, however, I recently realized that many useful tricks and interesting moments passed me by, maybe I’m not the only one, so I decided to list them here, I hope these techniques will be useful to someone at work or will prompt them to get acquainted with this language closer.

As in many languages, python 1 is equivalent to True, and 0 is False, that is:


1 == True

It would seem, and that in this? However, this has some side effects associated with the fact that identical objects must have the same hash, so you will not be able to cram the key 1 and True into one dictionary.


>>> a = {1: "one", 0: "zero", True: "true", False: "false"}
# -> {1: 'true', 0: 'false'}

This also allows the following operations:


>>> print(2 * False + True)
# -> 1

In this example, strings were used as dictionary values, however, I often wanted to use them as dictionary keys, I was always irritated that when creating a dictionary with braces, the lines should be quoted, I would like to omit them, it is possible, if you create a dictionary through the dict () constructor.


>>> {"one": 1, "two": 2, "three": 3} == dict(one=1, two=2, three=3)
# -> True

Guido van Rossum Photo

In addition, with the help of curly braces, not only dictionaries are created, but also sets (set).


>>> a = {1, 2, 3}

To unify the two sets, I somehow want to use the + operator, probably because of the way the string is concatenated. However, python does not support this operator for sets. But of course, this does not mean that we always have to use functions, the creators approached this issue more systematically and added support for basic operations on sets (and not just unions) in the language and “hung” them on logical operators.


a = {1, 2, 3}
b = {0, 2, 4}
print (a & b) # -> {2}
print (a | b) # -> {0, 1, 2, 3, 4}
print (a ^ b) # -> {0, 1, 3, 4}
print (a - b) # -> {1, 3}, however one arithmetic
# the operator still left

Continuing the conversation about dictionaries, since version 3.7 of the language specification it is guaranteed that the dictionaries retain the order of insertion of the elements, OrderedDict is no longer needed.


d = dict(zero='Cero', one='Uno', two='Dos', three='Tres', four='Cuatro',
five='Cinco', six='Seis', seven='Siete', eight='Ocho', night='Nueve')

for index, (key, value) in enumerate(d.items()):
print(f"{index} is {key} in England and {value} in Spain")

Note the output line, it starts with the prefix f – this is a special type of string introduced in python 3.6.

In total, there are three kinds of lines in the language: ordinary ones, denoted by quotes without prefixes, raw\not processed (raw), in which special characters, like, \n are not processed and inserted as text and f-lines.

They were created to simplify the output, python supports a huge number of output methods:


print ("result" + str (2)) # Simple string concatenation, python does not implement
# automatic reduction of all arguments to
# string type, it remains for the programmer
print ("result", 2) # print can take multiple arguments separated by commas,
# in this case they will be output through a space,
# you do not need to convert the output to a string,
# unlike the previous method
print ("result% d"% 2) #% -syntax is made by analogy with the C language.
print ("result% d% .2f"% (2, 2)) # https://docs.python.org/3.4/library/string.html#formatspec
print ("result% (name) s"% {"name": 2}) # also allowed to create named tags

print ("{}" format (2)) # The string class has a format () method
# it allows to omit the type of the output variable
print ("{0} {1} {0}". format (1, 2)) # you can also specify the variable number and thus
# print it twice
# numbering starts from zero
# if the number of passed variables is less than used in the output, an exception will be thrown
print ("{} {}" format (2)) # -> IndexError: tuple index out of range
print ("{0} {0}". format (2, 3)) # -> 2 2 However, if too many variables are passed
# code will work without errors
from math import pi # this output also supports format strings
print ("{:. 2f}". format (pi)) # -> 3.14

from string import Template # is possible and such a way of output
s = Template ("result $ res") # but it did not get much spread
print (s.substitute (res = [3, 4]))

Now we added f-lines. They are accessible to any variables from the scope, you can call functions, get items by key, in addition, they support format strings.


from math import pi
result = 4
name = "user"
print(f"{name:84s} pi= {pi:.2f}, result={result}, {name[2]}")
# -> user pi= 3.14, result=4, e

from datetime import datetime
print(f"{datetime.now():%Y:%m-%d}")

They are faster than all other output methods, so if you have python3.6 available, it’s recommended to use them.

One of the coolest python chips is that it packs and unpacks not objects and primitives, but parameters and collections.


def func(*argv, **kwargs)

However, there is one architectural flaw in the implementation:

  • argv is a tuple, its values can not be changed, you can not add or delete values
  • kwargs is a dictionary that can be changed, so caching is impossible

The disadvantage, of course, is not great, but it’s still unpleasant that you can not directly transfer kwargs to a cache based on a dictionary, on the other hand, if you add a list to the tuple, then such a tuple can not just be added to the dictionary.

Sets are also created based on a hash table, which means that the values must be hashed, in addition, the set itself is a variable and not hash type, there is a special type of frozenset – an unchangeable set (do not ask me why it is needed).

  • Discussed the creation of the type frozendict, but so far it has not been added (although at least one application already exists – as kwargs). For an immutable dictionary, you have to blow away namedtuple. And also for the records and unpretentious classes.

Who wrote the cycles in the student’s school years for the output of the values of the array and raged about the comma at the end, each time he decided, scored or rewritten to be beautiful, and only on the course 2-3 learned about the join method? Or am I the only one?

One of the unpleasant features of the join method for strings is that it works only with string elements, if there is at least one non-string in the collection, you have to use the generator expression, which looks too complicated for such a simple task, however, there is a way to simplify the output of list values (without brackets).


a = list(range(5))
print(" ".join(a)) # -> TypeError: sequence item 0: expected str instance, int found
print(" ".join(str(i) for i in a)) # -> 0 1 2 3 4
print(*a) # -> 0 1 2 3 4

Since the lines are also collections, they can also be “jointed”.


print('-'.join("hello")) # -> h-e-l-l-o

Consider the string from the previous example.


print(" ".join(str(i) for i in a)) # -> 0 1 2 3 4

The generator expression is passed to the join function without any parentheses, parentheses can be omitted to simplify the code reading. Python takes care of expressiveness.


print(" ".join(str(i) for i in a)) # -> 0 1 2 3 4

In addition, parentheses can also be omitted when creating tuples:


article = "python", 2018, "LinearLeopard" # announcement of the tuple
theme, year, author = "python", 2018, "LinearLeopard" # unpacking the tuple
theme, year, _ = "python", 2018, "LinearLeopard" # left and right should
# be the same number
# variables, you can emphasize,
# that you do not need something,
# denoting it through
# underscore
theme, _, _ = "python", 2018, "LinearLeopard" # names can be repeated
theme, * author = "python", 2018, "LinearLeopard" # can declare greedy
# parameter that will eat
# all inappropriate,
# of course, let's say
# only one
# greedy operator

Guido van Rossum Photo

The asterisk can also be used in function declarations, so you can create parameters that you can specify only by the key.


def sortwords(*wordlist, case_sensitive=False):

You can send as many parameters as you like without fear that one of them will be perceived as the value of the case_sensitive parameter.

Could be so.


def func(first, second, *, kwonly):

Let’s take a closer look, than just * differs from * args.


def func (first, second, *, kwonly = True):
print (first, second, kwonly)

def func2 (first, second, * args, kwonly = True):
print (first, second, * args, kwonly)

func (1) # -> TypeError: func () missing 1 required positional argument: 'second'
func (1, 2) # -> 1 2 True
func (1, 2, False) # -> TypeError: func () takes 2 positional arguments but 3 were given
# using * in the ad you specify that
# Your function should be called with two
# item parameters
func (1, 2, kwonly = False) # -> 1 2 False

func2 (1, 2, False) # -> 1 2 False True
args will take all positional
# parameters, that is, your function can be
# call with unlimited (> 2) number
# options

With the default parameters, one interesting feature is related: they are computed at the stage of compiling the module into bytecode, so it’s better not to use the mutable types there. We declare a function that adds an element to the end of the list, if the second argument is omitted, the function returns a new list containing only this element.


def add_to (elem, collection = []):
collection.append (elem)
return collection

a = ["a", "c"]
print (add_to ("b", a)) # -> ['a', 'c', 'b']

print (add_to ("a")) # -> ['a']
print (add_to ("b")) # -> ['a', 'b'] Where is 'a' from here?

The default value of the function is stored in the __defaults__ field, you can find out at any time what is there.


print(add_to.__defaults__) # -> (['a', 'b'],)

Since the default argument (empty list) was created at the time the program was started and is not recreated every time, we got this behavior.

You can correct this behavior if you make the default value an immutable type, and create a list in the body of the function:


def add_to(elem, collection=None):
collection = collection or []
collection.append(elem)
return collection

Pay attention to the command


collection = collection or []

This is a shorter (and less understandable, although not for everyone) analog


collection = collection if collection else []

In the next part, we will dig a much deeper and cover more details related to the Python.