I know, but I can't stop--Python is a collection of common mistakes

Even if you know the language specifications, there is a mistake that you will end up doing it. I inadvertently summarized the mistakes that I tend to make.

Forget to add commas in an array of strings

In Python, continuous writing of string literals will automatically concatenate them.

>>> "aaa" "bbb"
'aaabbb'

Thanks to this, if you forget to add a comma when defining an array of string literals, you may not notice it because it does not cause an error.

>>> [
... 1  #If you forget to add a comma other than a character string, an error will occur.
... 2
  File "<stdin>", line 3
    2
    ^
SyntaxError: invalid syntax

>>> [
... "a"  #For string literals, forgetting to add a comma does not cause an error
... "b",
... "c"
... ]
['ab', 'c']

Create a variable with the same name as the built-in function / built-in type

This is a mistake that beginners tend to make. For example, when you create a list and assign it to a variable, you give it the variable name list.

>>> list((1, 2, 3))
[1, 2, 3]
>>> list = list((1, 2, 3))
>>> list = list((1, 2, 3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable

If you give the variable name list, you will not be able to calllist ()after that.

--Built-in functions -Built-in type

Create a module with the same name as the standard module

It's common to create a file named test. * When you want to do some quick confirmation. But you can't do this in Python. Because there is a test in the standard module, the names will conflict.

Be careful not to use the same name, as many standard Python modules have very common names other than test.

Don't make test.py in Python! --Qiita [python] 10 real pitfalls of Python that are too detailed to convey | My Koiwa stapler

Forget to put a comma in a tuple with one element

Tuples are defined by separating them with commas, such as x, y, z, but when there is one element, they must be followed by a comma, such asx,.

>>> 1, 2, 3
(1, 2, 3)
>>> 1,
(1,)

When actually using tuples, due to the structure of the sentence, it is often used by enclosing it in () like (x, y, z), but for this reason it is enclosed in () For example, if you think that it is a tuple, you will make a mistake of forgetting to add a comma when there is only one element.

>>> (1, 2, 3)  # ()If you think that it will be a tuple if you surround it with...
(1, 2, 3)
>>> (1)  #Forget to put a comma when there is only one element
1

To avoid this, make it a habit to put a comma after the last element even when there are multiple elements.

>>> (1, 2, 3,)  #If you have a habit of putting a comma after the last element...
(1, 2, 3)
>>> (1,)  #Make no mistake when there is only one element
(1,)

Wrong import for a class or function with the same name as the module name

Some standard modules have a class or function with the same name as the module name. For example, datetime.datetime or pprint.pprint.

Of course, the way to write the code to call differs between importing a module and importing an internal class, but it is easy to make a mistake if the module and class have the same name.

Especially when the import statement is inserted by the completion function of the IDE, the module may be imported but the internal class may be imported, and vice versa.

When importing modules


import datetime
datetime.datetime.now()

When importing a class


from datetime import datetime
datetime.now()

Confuse attribute references with dictionary references

In Python, ʻobject.name is used to refer to an object attribute, and ʻobject [" name "] is used to refer to a dictionary element.

In JavaScript, ʻobject.name and ʻobject [" name "] have the same result, but in Python they behave clearly differently.

See object attributes


>>> class A(object):
...     def __init__(self):
...         self.attr1 = 123
... 
>>> a = A()
>>> a.attr1
123
>>> a["attr1"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'A' object is not subscriptable

See dictionary elements


>>> b = {"key1": 123}
>>> b["key1"]
123
>>> b.key1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'key1'

The existence check method is also different: the object attribute is hasattr (object," name "), and the dictionary element is " name "in object. Note that an error does not occur even if you write an attribute existence check for a dictionary object.

Existence check of object attributes


>>> a = A()
>>> "attr1" in a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument of type 'A' is not iterable
>>> hasattr(a, "attr1")
True

Check for the existence of dictionary elements


>>> b = {"key1": 123}
>>> "key1" in b
True
>>> hasattr(b, "key1")  #No exceptions occur!
False

Illusion of class variables as instance variables

In Python, instance variables and class variables are created as follows.

class A(object):
    val1 = [1, 2, 3]  #Class variables
    def __init__(self):
        self.val2 = [4, 5, 6]  #Instance variables

Writing class variables in Python is similar to defining instance variables in a statically typed language. Also, since you can access class variables with self.name as well as instance variables, you may think that you are manipulating instance variables, but they were actually class variables.

>>> class A(object):
...     val = [1, 2, 3]  #I intended to create an instance variable
... 
>>> a = A()
>>> b = A()
>>> a.val  #Can be accessed like an instance variable
[1, 2, 3]
>>> b.val
[1, 2, 3]
>>> a.val.append(10)  #I think I'm manipulating an instance variable of object a...
>>> a.val
[1, 2, 3, 10]
>>> b.val  #Object b has also changed...
[1, 2, 3, 10]
>>> A.val  #I was actually manipulating class variables
[1, 2, 3, 10]

Overwrite instance method with instance variable

In Python, you cannot use the same name for an instance method and an instance variable at the same time. Given that a function is a first-class citizen and a dynamically typed language, it's not surprising that if you assign a value to an instance variable with the same name as the instance method, the instance method will be overwritten with the value. I will.

>>> class A(object):
...     def hoge(self, x):
...         self.hoge = x  #I intend to set it in an instance variable hoge that is different from the method hoge
... 
>>> a = A()
>>> a.hoge(123)  #At this point a.hoge is a method so you can call it
>>> a.hoge(456)  #At this point a.hoge is a number(123)I can't call it because it's
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

--The instance method hoge is kept as a class variable hoge. (See ʻA.hoge) --When you refer to self.hoge, the class variable is referenced if there is no instance variable. --When you write an assignment statement with self.hoge = 123, it is assigned to the instance variable hogeregardless of the presence or absence of the class variablehoge`.

Forget to add decorators by overriding class and static methods

In Python, class methods and static methods are defined with decorators.

class A(object):
    @classmethod
    def hoge(cls, x):
        pass
    @staticmethod
    def meke(x):
        pass

In addition, class methods and static methods can be overridden in subclasses as well as instance methods. In that case, the overridden method must have the same decorator as the superclass. (Unless you dare to change the characteristics of the method)

class B(A):
    @classmethod  #Also needed when overriding
    def hoge(cls, x):
        pass
    @staticmethod  #Also needed when overriding
    def meke(x):
        pass

If you forget to add the decorator when overriding, it will not cause an error by itself, but be careful because the value of the first argument will change to the instance object (self).

If you do it with PyCharm complement, it will not take over to the decorator, so I sometimes make mistakes.

Specify an object or dynamic value as the default argument

The value of the function's default argument is evaluated only once when the function is defined. It is not evaluated every time you call a function.

>>> class A(object):
...     def __init__(self):
...         print("A()Was called!")
... 
>>> def hoge(a=A()):
...     print("hoge()Was called!")
... 
A()Was called!#Default arguments are evaluated immediately after defining hoge
>>> hoge()
hoge()Was called!#Default arguments are not evaluated when hoge is called
>>> hoge()
hoge()Was called!

For this reason, using the following values as default arguments will result in disappointing results.

--Objects such as arrays and dictionaries

```pycon

def append(v, l=[]): ... l.append(v) ... return l ...

append(1) #Add 1 to empty array [1]

append(2) #Add 2 to empty array...Should be... [1, 2]


 --Dynamic values such as current date and time

    ```pycon
>>> from datetime import datetime
>>> import time
>>> def printtime(t=datetime.now()):
...     print(t)
... 
>>> printtime()
2016-02-07 12:30:00.000000
>>> time.sleep(5)  #Wait 5 seconds
>>> printtime()
2016-02-07 12:30:00.000000  #Time has stopped! ??

To avoid this, set the default value to None and set the original value in the function.

>>> def append(v, l=None):
...     if not l:
...         l = []
...     l.append(v)
...     return l
... 
>>> append(1)
[1]
>>> append(2)
[2]

I don't notice if I pass a string as an argument to pass an array

Python strings act as character iterators. Therefore, you may not notice it even if you forget to add [] when the argument calls the function of the array.

>>> def print_items(items):
...     for i, x in enumerate(items):
...         print("[%d]=%s" % (i, x))
... 
>>> print_items([1, 2])
[0]=1
[1]=2
>>> print_items(["ab"])  #To be correct, write like this...
[0]=ab
>>> print_items("ab")  # []If you forget to put on, it will be like this.
[0]=a
[1]=b
>>> print_items(["a"])  #But if it's one letter...
[0]=a
>>> print_items("a")  # []Even if you forget to put on, the result is the same, so you do not notice
[0]=a

Recommended Posts

I know, but I can't stop--Python is a collection of common mistakes
Mathematics is a graph of common tests.
[Complete memorandum] A collection of codes that I often use but cannot remember
Since Python 1.5 of Discord, I can't get a list of members
I did a lot of research on how Python is executed
[Kaggle] I made a collection of questions using the Titanic tutorial
i! i! ← This is a mathematical formula
A collection of one-liner web servers
I think the limit of knapsack is not the weight but the volume w_11/22update