Je sais, mais je ne peux pas m'arrêter - Python est une collection d'erreurs courantes

Même si vous connaissez les spécifications linguistiques, il y a une erreur que vous finirez par le faire. J'ai résumé par inadvertance les erreurs que j'ai tendance à faire.

Oubliez de mettre une virgule dans un tableau de chaînes

En Python, si vous écrivez une chaîne littérale successivement, elle sera automatiquement concaténée.

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

Grâce à cela, si vous oubliez d'ajouter une virgule lors de la définition d'un tableau de littéraux de chaîne, vous risquez de ne pas le remarquer car cela ne provoque pas d'erreur.

>>> [
... 1  #Si vous oubliez d'ajouter une virgule autre qu'une chaîne de caractères, une erreur se produira.
... 2
  File "<stdin>", line 3
    2
    ^
SyntaxError: invalid syntax

>>> [
... "a"  #Pour les chaînes littérales, oublier d'ajouter une virgule ne provoque pas d'erreur
... "b",
... "c"
... ]
['ab', 'c']

Crée une variable avec le même nom qu'une fonction intégrée / un type intégré

C'est une erreur que les débutants ont tendance à faire. Par exemple, lorsque vous créez une liste et l'assignez à une variable, vous lui donnez le nom de variable «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

Si vous donnez le nom de variable «list», vous ne pourrez plus appeler «list ()» après cela.

Créer un module avec le même nom que le module standard

Il est courant de créer un fichier nommé test. * Lorsque vous voulez faire quelque chose un peu. Mais vous ne pouvez pas faire cela avec Python. Parce qu'il y a un test dans le module standard, les noms seront en conflit.

Veillez à ne pas utiliser le même nom, car de nombreux modules Python standard ont des noms très communs autres que test.

Ne faites pas test.py en Python! --Qiita [python] 10 vrais pièges de Python qui sont trop détaillés pour être véhiculés | My Koiwa Hotchkiss

Oubliez de mettre une virgule dans un taple avec un élément

Les taples sont définis en les séparant par des virgules, comme «x, y, z», mais lorsqu'il y a un élément, ils doivent être suivis d'une virgule, comme «x».

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

Lorsque vous utilisez réellement un taple, il est souvent utilisé en le mettant entre () comme (x, y, z) en raison de la structure de l'instruction, mais à partir de là, il est inclus dans (). Par exemple, si vous pensez que ce sera un taple, vous ferez une erreur en oubliant d'ajouter une virgule lorsqu'il n'y a qu'un seul élément.

>>> (1, 2, 3)  # ()Si vous pensez que ce sera un taple si vous l'entourez de...
(1, 2, 3)
>>> (1)  #Oubliez de mettre une virgule quand il n'y a qu'un seul élément
1

Pour éviter cela, prenez l'habitude de mettre une virgule après le dernier élément, même s'il y a plusieurs éléments.

>>> (1, 2, 3,)  #Si vous avez l'habitude de mettre une virgule après le dernier élément...
(1, 2, 3)
>>> (1,)  #Ne vous y trompez pas quand il n'y a qu'un seul élément
(1,)

Importation incorrecte pour une classe ou une fonction avec le même nom que le nom du module

Certains modules standard ont des classes et des fonctions portant le même nom que le nom du module. Par exemple, «datetime.datetime» ou «pprint.pprint».

Bien sûr, la façon dont vous écrivez le code à appeler est différente lorsque vous importez un module et lorsque vous importez une classe interne, mais il est facile de se tromper si le module et la classe ont le même nom.

Surtout lorsque l'instruction d'importation est insérée par la fonction de complétion de l'EDI, la classe interne peut être importée même si le module était destiné à être importé, et vice versa.

Lors de l'importation de modules


import datetime
datetime.datetime.now()

Lors de l'importation d'une classe


from datetime import datetime
datetime.now()

Confondre les références d'attributs avec les références de dictionnaire

En Python, ʻobject.nameest utilisé pour faire référence à un attribut d'objet, et ʻobject ["name"]est utilisé pour faire référence à un élément de dictionnaire.

En JavaScript, ʻobject.nameet ʻobject ["name"]ont le même résultat, mais en Python ils se comportent clairement différemment.

Voir les attributs des objets


>>> 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

Se référer aux éléments du dictionnaire


>>> 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'

La méthode de vérification d'existence est également différente: l'attribut de l'objet est hasattr (object," name "), et l'élément du dictionnaire est "name" in object`. Notez que l'écriture d'un contrôle d'existence d'attribut pour un objet dictionnaire ne provoque pas d'erreur.

Vérifier l'existence d'attributs d'objet


>>> 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

Vérifier l'existence d'éléments de dictionnaire


>>> b = {"key1": 123}
>>> "key1" in b
True
>>> hasattr(b, "key1")  #Aucune exception ne se produit!
False

Imaginez une variable de classe comme variable d'instance

En Python, les variables d'instance et les variables de classe sont créées comme suit.

class A(object):
    val1 = [1, 2, 3]  #Variable de classe
    def __init__(self):
        self.val2 = [4, 5, 6]  #Variable d'instance

L'écriture de variables de classe en Python est similaire à la définition de variables d'instance dans un langage à typage statique. De plus, vous pouvez accéder aux variables de classe avec self.name de la même manière que les variables d'instance, vous pouvez donc penser que vous manipulez des variables d'instance, mais il s'agissait en fait de variables de classe.

>>> class A(object):
...     val = [1, 2, 3]  #J'avais l'intention de créer une variable d'instance
... 
>>> a = A()
>>> b = A()
>>> a.val  #Accessible comme une variable d'instance
[1, 2, 3]
>>> b.val
[1, 2, 3]
>>> a.val.append(10)  #Je pense que je manipule la variable d'instance de l'objet a...
>>> a.val
[1, 2, 3, 10]
>>> b.val  #L'objet b a également changé...
[1, 2, 3, 10]
>>> A.val  #Je manipulais en fait des variables de classe
[1, 2, 3, 10]

Écraser la méthode d'instance avec la variable d'instance

En Python, vous ne pouvez pas utiliser le même nom pour une méthode d'instance et une variable d'instance en même temps. Étant donné qu'une fonction est un objet de première classe et un langage typé dynamiquement, il n'est pas surprenant que si vous affectez une valeur à une variable d'instance avec le même nom que la méthode d'instance, la méthode d'instance sera écrasée par la valeur. Je vais.

>>> class A(object):
...     def hoge(self, x):
...         self.hoge = x  #J'ai l'intention de le définir dans une variable d'instance hoge qui est différente de la méthode hoge
... 
>>> a = A()
>>> a.hoge(123)  #À ce stade, un.hoge est une méthode donc vous pouvez l'appeler
>>> a.hoge(456)  #À ce stade, un.hoge est un nombre(123)Je ne peux pas l'appeler parce que c'est
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

Oubliez d'ajouter des décorateurs en remplaçant les méthodes de classe et les méthodes statiques

En Python, les méthodes de classe et les méthodes statiques sont définies avec des décorateurs.

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

De plus, les méthodes de classe et les méthodes statiques peuvent être remplacées dans les sous-classes ainsi que les méthodes d'instance. Dans ce cas, la méthode remplacée doit avoir le même décorateur que la superclasse. (À moins que vous n'osiez changer les caractéristiques de la méthode)

class B(A):
    @classmethod  #Également requis lors du remplacement
    def hoge(cls, x):
        pass
    @staticmethod  #Également requis lors du remplacement
    def meke(x):
        pass

Si vous oubliez d'ajouter le décorateur lors du remplacement, cela ne causera pas d'erreur en soi, mais soyez prudent car la valeur du premier argument changera en objet d'instance (self).

Si vous le faites avec PyCharm complément, il ne prendra pas le relais du décorateur, donc je fais parfois des erreurs.

Spécification d'un objet ou d'une valeur dynamique comme argument par défaut

La valeur de l'argument par défaut de la fonction n'est évaluée qu'une seule fois lorsque la fonction est définie. Il n'est pas évalué à chaque fois que vous appelez une fonction.

>>> class A(object):
...     def __init__(self):
...         print("A()A été appelé!")
... 
>>> def hoge(a=A()):
...     print("hoge()A été appelé!")
... 
A()A été appelé!#Les arguments par défaut sont évalués immédiatement après la définition de hoge
>>> hoge()
hoge()A été appelé!#Les arguments par défaut ne sont pas évalués lorsque hoge est appelé
>>> hoge()
hoge()A été appelé!

Pour cette raison, l'utilisation des valeurs suivantes comme arguments par défaut entraînera des résultats décevants.

--Objets tels que des tableaux et des dictionnaires

```pycon

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

append(1) #Ajouter 1 au tableau vide [1]

append(2) #Ajouter 2 au tableau vide...Devrait être... [1, 2]


 --Valeurs dynamiques telles que la date et l'heure actuelles

    ```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)  #Attendez 5 secondes
>>> printtime()
2016-02-07 12:30:00.000000  #Le temps s'est arrêté! ??

Pour éviter cela, définissez la valeur par défaut sur Aucun et définissez la valeur d'origine dans la fonction.

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

Je ne remarque pas si je passe une chaîne comme argument pour passer un tableau

Les chaînes Python agissent comme des itérateurs de caractères. Par conséquent, vous ne le remarquerez peut-être pas même si vous oubliez d'ajouter [] lorsque l'argument appelle la fonction du tableau.

>>> 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"])  #Pour être correct, écris comme ça...
[0]=ab
>>> print_items("ab")  # []Si vous oubliez de le mettre, ce sera comme ça.
[0]=a
[1]=b
>>> print_items(["a"])  #Mais si c'est une lettre...
[0]=a
>>> print_items("a")  # []Même si vous oubliez de mettre, le résultat est le même, donc vous ne remarquez pas
[0]=a

Recommended Posts

Je sais, mais je ne peux pas m'arrêter - Python est une collection d'erreurs courantes
[Note complète] Une collection de codes que j'utilise souvent mais dont je ne me souviens pas
Discord's Python 1.5 ou version ultérieure, je ne parviens pas à obtenir la liste des membres
J'ai fait beaucoup de recherches sur la façon dont Python est exécuté
[Kaggle] J'ai fait une collection de problèmes en utilisant le didacticiel Titanic
i! i! ← Ceci est une formule
Une collection de serveurs Web à une seule ligne
Je pense que la limite du sac à dos n'est pas le poids mais le volume w_11 / 22update