Je regarde un cas comme celui-ci:

def parse_item(self, response):

    item = MetrocItem()

    def ver(string):
        if string:
            return string
        else:
            return 'null'

    item['latitude'] = ver(response.xpath('//input[@id="latitude"]/@value').extract_first())

Cela fonctionne, mais existe-t-il une meilleure façon de procéder?

3
Emiliano Isaza Villamizar 16 avril 2018 à 18:08

4 réponses

Meilleure réponse

Comme @Graipher l'a mentionné dans les commentaires, cela est certainement valable dans certains cas, mais dans votre cas particulier, ce n'est pas nécessaire. Si votre fonction dépend d'une variable locale, vous retournez une fermeture qui doit être reconstruite à chaque fois que vous appelez la méthode. Mais dans votre cas, la fonction va se comporter de la même manière chaque fois que vous appelez la méthode, il serait donc plus logique de la définir globalement comme méthode privée, ou même comme lambda dans votre cas.

ver = lambda x: x if x else 'null'

Mais l'approche préférée serait de simplement le définir globalement et de commencer le nom par un trait de soulignement pour clarifier l'intention.

def _ver(string):
    ...
3
Silvio Mayolo 16 avril 2018 à 15:14

Ce n'est pas une mauvaise pratique, mais voici une alternative.

Étant donné que cette petite fonction ne dépend de rien dans parse_item et que vous souhaiterez qu'elle ne soit construite qu'une seule fois, pour des performances, vous pouvez le faire:

def parse_item(self, response):
    ...

def _ver(string):
    ...

parse_item.ver = _ver
del _ver

Et faites-y référence dans parse_item comme parse_item.ver au lieu de simplement ver. Cela évite d'encombrer l'espace de noms global, même avec une méthode soulignée que Python cache partiellement pour vous.

J'aurais recommandé l'expression lambda comme une autre alternative, mais Silvio y est arrivé en premier.

De plus, le fait de dire qu'il pourrait s'agir d'une fonction globale, visible par tous, n'a de sens que s'il y a une chance qu'elle puisse être utilisée ailleurs.

Vous pouvez également éliminer complètement cet exemple, comme l'ont suggéré doctorlove et Niklas, mais je suppose que vous entendez cela comme un exemple de cas plus complexes.

1
Jim Pivarski 16 avril 2018 à 15:19

Vous pouvez vous débarrasser complètement de cette fonction:

string = response.xpath('//input[@id="latitude"]/@value').extract_first()
item['latitude'] = string if string else 'null'
2
Niklas Mertsch 16 avril 2018 à 15:16

Il existe des cas d'utilisation pour avoir une fonction locale - que ce soit dans une méthode de classe ou une autre méthode, dites si vous voulez une fermeture capturant quelque chose de local.

Dans votre cas, vous voulez quelque chose comme un null colasecing:

Par exemple.

>>> s = None
>>> s or "None"
'None'

Vous pouvez donc utiliser

item['latitude'] = response.xpath('//input[@id="latitude"]@value').extract_first() or "null"
1
doctorlove 16 avril 2018 à 15:17