Czy istnieje jakiś zalecany / ogólnie akceptowany styl kodowania do obsługi sytuacji, w których funkcja zwraca krotkę wartości, ale później używana jest tylko jedna z tych wartości (zwróć uwagę, że jest to głównie przeznaczone dla funkcji bibliotecznych, których nie mogę zmienić - pisząc opakowanie połączenie jest prawdopodobnie trochę przesadzone…)? Zamiast robić
a, b, c = foo()
a następnie po prostu nie używam b
i c
, który z poniższych wariantów powinien być preferowany (czy jest inny?):
Wariant 1 (podkreślenie)
a, _, _ = foo()
(co jest bardzo jasne i proste, ale może kolidować z _ = gettext.gettext
używanym w wielu aplikacjach korzystających z tłumaczenia)
Wariant 2 (nazwa manekina)
a, unused, unused = foo()
(myślę, że niezbyt pociągające, to samo dotyczy innych nazw, takich jak dummy
)
Wariant 3 (indeks)
a = foo()[0]
(dla mnie ()[0]
wygląda to nie pytonicznie…)
python
coding-style
użytkownik49643
źródło
źródło
a, b = foo()[0:2]
zadziała? Jeśli tak: tak, to robi :)a, *_ = foo()
odrzuci wszystkie wartości oprócz pierwszej.Odpowiedzi:
Użycie znaku podkreślenia dla nieużywanych zmiennych jest zdecydowanie dopuszczalne. Ostrzegamy jednak, że w niektórych bazach kodów nie jest to opcja, ponieważ ten identyfikator jest zarezerwowany jako skrót
gettext
. Jest to najczęstszy sprzeciw wobec tego stylu (choć, jak sądzę, nie stanowi to problemu dla większości). Nadal go polecam i zawsze używam go sam.Nazwy lubią
dummy
lubunused
drażnią mnie osobiście, i nie widzę ich zbyt często (w Pythonie, to znaczy - znam bazę kodów Delphi, która używadummy
swobodnie, i przeciekała również do skryptów związanych z danym programem). Odradzałbym ci to.Wystarczy wyodrębnić jeden element ze zwróconej krotki. Oszczędza to również kłopotów z prawidłową liczbą nieużywanych wartości. Pamiętaj jednak, że ma on dwie potencjalne wady:
źródło
Pylint nauczył mnie robić to w ten sposób:
Oznacza to, że nieużywane wyniki mają opisową nazwę poprzedzoną przez _. Pylint uważa miejscowych z przedrostkiem _ za nieużywane, a globale lub atrybuty z przedrostkiem _ jako prywatne.
źródło
Jeśli w całym swoim projekcie robisz to tylko raz lub bardzo rzadko, aby napisać konkretną funkcję, użyłbym wariantu 1, jeśli wiesz, że
gettext
nie jest problemem w tym module, a inaczej wariant 3.Z drugiej strony, jeśli często to robisz - a zwłaszcza jeśli za każdym razem chcesz innego podzbioru wartości zwracanych (tworzenie opakowania po prostu zwracającego te, na których Ci zależy, to nieopłacalne), może być korzystne napisanie opakowania który umieszcza wyniki w nazwanej krotce lub instancji innej klasy opisowej, co pozwoli ci wykonać:
A potem pracuj z
bar.a
,bar.b
ibar.c
.źródło
Jak powiedzieli inni, podkreślenie (
_
) jest standardem. Ale jeśli do tłumaczenia używa się podkreślenia, myślę, że podwójny podkreślenie jest najlepszą alternatywą.var, __, value = "VAR=value".partition('=')
Lepsze niż te:
var, unused, value = "VAR=value".partition('=')
var, unused_del, value = "VAR=value".partition('=')
var, _del, value = "VAR=value".partition('=')
źródło
Jestem programistą niebędącym Pythonem, ale dla mnie trzeci wariant jest najbardziej sensowny.
W wariancie 3 masz absolutną jasność, z jakimi wartościami chcesz się zmierzyć. W wariancie 1 i 2 wartości są przypisywane z powrotem do zmiennych, dzięki czemu można ich użyć. Być może nazwałeś je niejasno, ale złe nazewnictwo nie jest tak naprawdę rozwiązaniem żadnego problemu.
Oprócz przejrzystości, dlaczego chcesz przypisać nieużywane wartości do gniazda w pamięci (jak w wariantach 1 i 2)? To byłoby złe rozwiązanie w zakresie zarządzania pamięcią.
źródło
Oto ogólna zasada: jeśli zostanie użyta tylko 1 ze zwróconych wartości, dlaczego po prostu nie zwrócić tej 1 wartości? W przypadku, gdy flaga jest wywoływana z wielu miejsc, zachowaj flagę dla tej samej wartości i zwróć wartości zgodnie z flagą.
EDYTOWAĆ:
Gdybym był w twojej sytuacji i nie napisałem funkcji, być może wybrałbym wariant 2. Zachowałbym tam nazwy manekinów, aby w razie potrzeby móc użyć parametrów. Krojenie listy będzie trochę kosztowne. Być może możesz zaoszczędzić kilka bajtów, aby otrzymać niechciane dane.
źródło
%timeit a, _, _ = foo()
porównaniu%timeit a = foo()[0]
do 123ns vs. 109ns, tzn. Krojenie wydaje się być rzeczywiście szybsze niż rozpakowywanie wartości. A może miałeś na myśli jakąś konkretną sytuację?