Preferowanie Pythona zamiast C w programowaniu algorytmicznym


16

Studiowałem trochę algorytmów i patrzyłem na strony takie jak SPOJ.pl TopCoder itp. Widziałem, że programiści preferują C lub C ++ zwykle w większości konkursów programowania algorytmicznego.

Teraz mam ostatnio problemy. Znam trochę C i Pythona, a kiedy próbuję napisać kod, wydaje mi się, że wolę Pythona od C dla większości algorytmów. Za każdym razem, gdy siadam, aby napisać kod w CI, poddaję się po około 15 minutach, ponieważ uważam, że jest to zbyt kłopotliwe i zwykle przechodzę do Pythona. Przekazywanie macierzy Wskaźniki i tak dalej wydają się być bezużytecznym marnowaniem czasu, który mógłbym wykorzystać do myślenia o samym algorytmie.

Teraz wiem i słyszałem od wielu ludzi, że C jest bardzo ważnym językiem i jest chlebem powszednim wielu programistów.

Chciałem wiedzieć, czy to moje podejście ma jakieś wady / konsekwencje / wady itp.

To nie jest debata Python kontra C; To pytanie o to, w jaki sposób ta szczególna praktyka preferowania Pythona nad C ze względu na łatwość użycia wpłynie na mnie lub dowolnego innego programistę / naukowca na dłuższą metę.


Bardzo chciałbym usłyszeć od osób, które używały tych języków w branży / i / lub do opracowania dużego oprogramowania / bibliotek itp.


ten temat nie będzie kompletny bez linku do tej dyskusji lukeplant.me.uk/blog/posts/…
permeakra

11
@ermermra: To tylko rant, w zasadzie stwierdzenie, że nauka Haskella i Pythona nie poprawia ci znajomości innych języków, ponieważ te inne języki są do kitu.
Robert Harvey

Nie jest to tylko rant, ponieważ zawiera opis, w jaki sposób Python i Haskell wpływają na umysł użytkownika, oraz wiele komentarzy innych osób na ten temat. W porównaniu z nim nie używa c jako języka niskiego poziomu, ale jest nieco bardziej zaawansowanym językiem, ale pomysł jest taki sam - zaczyna się przenosić pomysły z innego języka na język, w którym obecnie pracuje, czyniąc kod nieidiomatycznym . To może być dobra rzecz, ale ...
permeakra


Byłoby interesujące zobaczyć trochę programowania nie algorytmicznego , cokolwiek to jest.
SK-logic

Odpowiedzi:


14

Z mojego doświadczenia wynika, że ​​gdy ludzie mają nadmierne problemy z kodowaniem algorytmów w C, często dzieje się tak, ponieważ ściśle łączą zarządzanie strukturą danych z algorytmem zamiast tworzyć odpowiednie abstrakcje. Na przykład, ręcznie manipuluj połączonymi wskaźnikami list wszędzie zamiast tworzenia push()i pop()funkcji. Są zbyt przyzwyczajeni do dostarczania im tych abstrakcji.

Podczas gdy ten problem jest znacznie bardziej widoczny w przypadku abstrakcji niższego poziomu, brak rozpoznania ścisłego powiązania i tworzenia odpowiednich abstrakcji jest problemem na każdym poziomie. Ćwiczenie tych umiejętności w C, dopóki nie będziesz w stanie stworzyć algorytmu, który wygląda na czysty i czytelny, zostanie przeniesiony na dowolny używany język.

Innym problemem, który czasami widzę wśród programistów Pythona, jest trudność dostosowania się do wydajności na dużą skalę. To prawda, że ​​wydajność nie jest zwykle głównym problemem, ale najbardziej pythoniczny sposób implementacji algorytmu dla stosunkowo małej struktury danych może zatrzymać system, gdy pracujesz z gigabajtami lub więcej danych. Stanie się dobrym programistą C pomaga ci być bardziej świadomym tego rodzaju problemów w dowolnym języku.

Czy potrafisz nauczyć się tych umiejętności w innych językach? Jasne, ale C pomaga, czyniąc to bardziej oczywistym, gdy popełnisz błąd.

Biorąc to pod uwagę, używam Pythona do programowania algorytmicznego, kiedy mam wybór, nawet jeśli tak samo dobrze czuję się w C. Python ma funkcje językowe, które sprawiają, że jest bardzo przyjemny dla tego rodzaju programowania, a różnice w wydajności są zwykle znikome. Nie mogę powiedzieć, dlaczego inni programiści, którzy znają oboje, wybiorą C. Wyobrażam sobie, że wielu z nich robi to po to, aby wyróżnić się z tłumu.


1
„Są zbyt przyzwyczajeni do dostarczania im tych abstrakcji”. Czy to zakłada, że ​​nauczyłem się Pythona przed C i dlatego nie jestem w stanie się przystosować lub coś w tym stylu?
ffledgling

10

Naukowcy, których głównym zainteresowaniem nie jest programowanie, wolą języki wyższego poziomu, takie jak Python, ponieważ mogą łatwiej kodować rozwiązanie w takich językach niż, powiedzmy, C. Python jest do tego szczególnie odpowiedni, ponieważ jest bardziej „prototypowy”, ponieważ jest „baterie w zestawie” i integruje się z bibliotekami numerycznymi, takimi jak NumPy i SciPy.

Jeśli badacz potrzebuje lepszej wydajności, zwykle przekazuje algorytm utworzony w Pythonie Inżynierowi oprogramowania, który znajdzie sposoby na jego optymalizację (w tym przekodowanie w C).


Więc w zasadzie badacze i inżynierowie oprogramowania mają związek projektanta z człowiekiem? A co z wykorzystaniem obu rodzajów ludzi w branży?
ffledgling

9
Myślę, że na wynos jest to, że kodowanie algorytmu w Pythonie, a następnie napisanie bardziej dopracowanej implementacji w C, jest całkowicie akceptowalnym scenariuszem.
Robert Harvey

lub „przekodowywanie w Cython”?
endolith

10

Pamiętaj, SPOJ.pl, konkurs ACM i wszystkie podobne konkursy koncentrują się na szybkim tworzeniu działającego kodu, który zostanie wyrzucony zaraz po zawodach. TopCoder robi to, ale w mniejszym stopniu (kod jest przynajmniej właściwie zorganizowany na poziomie projektowania OO).

Jednak w prawdziwym świecie programowania prawie każdy skrót, który bierzesz w konkursach programowania algorytmicznego, jest anty-wzorcem. Tylko jeśli weźmiesz to pod uwagę, możesz dokonać dowolnego porównania. Weźmy twój przykład: przekazywanie wielowymiarowej tablicy między różnymi funkcjami. W środowisku konkursowym najlepszym podejściem byłoby po prostu zadeklarowanie tablicy jako globalnej, aby zaoszczędzić czas na ustalenie właściwych szczegółów wywołania (np. Czy powinienem przekazać rozmiar, czy można to ustalić?). W prawdziwym programowaniu zrobiłbym dokładnie odwrotnie.

Więc na twoje pytanie, czy są jakieś złożone konsekwencje wyboru Pythona zamiast C dla algorytmów, powiedziałbym, że nie. Jeśli interesuje Cię tylko algorytm, zrobisz to samo w Pythonie i C. Implementacja go w języku funkcjonalnym może przynieść pewne różnice, ale algorytm jest taki sam.

Praktycznie jedyną rzeczą, którą zyskałeś, wdrażając algorytm w C, jest większa kontrola nad wykonywaniem i gwarancja, że ​​używasz tylko abstrakcji niższego poziomu. To nie jest mała rzecz, ponieważ w Pythonie większość złożoności jest ukryta. Ale jeśli problem nie jest trywialny w abstrakcjach wyższego poziomu, możliwe, że straciłeś tylko szybkość wykonywania, aw większości przypadków tak naprawdę nie próbujesz zrobić programu tak szybko, jak to możliwe, po prostu uczysz się .

Jak już zasugerowano, zawsze można zamienić implementację Pythona na implementację C, jeśli Python okaże się zbyt wolny. Ale stanie się to prawdopodobnie 2-3 razy w wielkim projekcie, więc rozpoczęcie pracy w C może być stratą czasu, chyba że jest to Twój wybrany język (i wskazałeś, że tak nie jest).


1
Gdyby napisać prawdziwą aplikację intensywnie wykorzystującą matematykę, prawie na pewno wybrałby C lub C ++ (nie ma czegoś takiego jak „C / C ++”) ze względu na ogromny wzrost wydajności w stosunku do dowolnego interpretowanego języka. Patrzyłem na Topcoder kilka lat temu i pamiętam, że widziałem dużo C ++, które bezmyślnie wyciekły z pamięci, ponieważ w konkursach nie dbano o drobne szczegóły, takie jak wycieki. Nie byłem pod wrażeniem.
Jim In Texas

Właśnie o to mi chodzi. To kwestia priorytetów: topcodery nie dbają o wycieki pamięci, ponieważ jądro i tak je wyczyści; nie dbają o złe praktyki ani anty-wzorce, jeśli oszczędzają czas.
K.Steff,

2
Twój ostatni akapit ucieleśnia złotą zasadę: „spraw, by działało, a następnie spraw, aby było szybkie”.
Carson63000,

9

Jako długoletni członek TopCoder i okazjonalny użytkownik SPOJ mogę powiedzieć, że głównym powodem, dla którego wolę C / C ++ od innych języków w konkursach, jest jego surowa szybkość. Kiedy wykonanie programu jest zaplanowane na czas, istnieje ogromna presja, aby wybrać „najszybszy” język, jaki można uzyskać, ponieważ daje to więcej luzu w zakresie kodowania algorytmu. Mój postęp w TC przeszedł z Javy do C # na C ++.

Jednak taka sytuacja występuje częściej w konkursach niż w codziennym programowaniu: chociaż pisanie optymalnego kodu jest niezwykle ważne, względne znaczenie ukończenia kodu tak szybko, jak to możliwe, i uczynienie go tak łatwym do utrzymania, jak to zwykle możliwe, zwykle oszczędza kilka sto cykli procesora. Jeśli wygodniej kodujesz coś w Pythonie, bardzo często jest to preferowane rozwiązanie.

Ponadto Python oferuje funkcje wysokiego poziomu, które nie są dostępne w C ++. Budowanie ich jest często bardzo kosztowne, a czasem nawet niemożliwe (na przykład rozważ zbudowanie refleksji lub samodostosowującego się kodu w C ++). W takich przypadkach opieranie się na języku wyższego poziomu może również okazać się optymalnym rozwiązaniem.


Ponieważ jesteś użytkownikiem TC i SPOJ. Czy kompromis między czasem a prostotą jest bardzo duży, jeśli używamy Pythona do kodu? Czy to jest możliwe, aby pomyślnie przesłać za pomocą Pythona, jeśli ten sam algorytm można pomyślnie przesłać za pomocą C? (Tak, wiem, że pytanie to będzie / może znacznie się różnić w zależności od pytania, ale czy w większości przypadków będzie to
niekorzystne,

@Ayos Nie mogę mówić w języku Python, ponieważ nigdy nie użyłem go w kontekście TC lub SPOJ, ale przewaga C ++ nad C # i Javą jest tylko czasami ważna, a nawet wtedy nie jest zbyt znacząca. Pamiętam tylko jeden przypadek, gdy prosty port algorytmu, który został zakodowany w C ++ do C #, zawiódł z powodu przekroczenia limitu czasu, ale było to w pokoju ćwiczeń. W większości przypadków odkrywanie poprawnego algorytmu jest jedyną różnicą między udanymi i nieudanymi zgłoszeniami.
dasblinkenlight

1
Zauważ, że interpretowane języki, takie jak Python, Ruby i Perl, działają kilka razy wolniej niż skompilowane języki wysokiego poziomu, takie jak Java i C # (które same są powolne w porównaniu do C). Ostatecznie jednak nie ma to znaczenia, chyba że planujesz pracować z wyjątkowo dużymi zestawami danych lub potrzebujesz prędkości w czasie rzeczywistym.
KChaloux,

5

Za każdym razem, gdy siadam, aby napisać kod w CI, poddaję się po około 15 minutach, ponieważ uważam, że jest to zbyt kłopotliwe i zwykle przechodzę do Pythona.

Ten wzrost wydajności jest częstym powodem znacznego zmniejszenia liczby zadań w C i C ++.

To pytanie o to, w jaki sposób ta szczególna praktyka preferowania Pythona nad C ze względu na łatwość użycia wpłynie na mnie lub dowolnego innego programistę / naukowca na dłuższą metę.

Składają się na to dwie zasadnicze części. Pierwszym z nich jest programowanie algortihmic. Naprawdę nie ma znaczenia, jakiego języka użyjesz do wyrażenia algorytmu. Praca z samym algorytmem i dopasowanie właściwych do właściwych problemów to kluczowe elementy, więc nie ma prawdziwego problemu.

Druga część to wzrost wydajności. Używanie rzeczy, które zwiększają produktywność w miarę upływu czasu, to dobry nawyk i coś, co nie przyniesie ci nic poza korzyściami podczas kariery. Umiejętność wyrażania algorytmów w różnych językach jest bardzo pomocna, ale ta pomoc opiera się bardziej na tym, jakie idiomy używają języki niekoniecznie w tych językach.

Krótko mówiąc, nie martw się tym . To, czego używasz do wyrażania algorytmu, jest o wiele mniej ważne niż możliwość wyrażenia go w ogóle.


3
„Zadania C i C ++ znacznie spadły”. Co? Wydaje się to zupełnie zaskakujące, ponieważ widzę odwrotny trend. -1, dopóki nie możesz podać źródła tej instrukcji.

3

Zaletą używania języków wyższego poziomu, takich jak Python lub Ruby, jest to, że (1) ich składnia jest bardzo zbliżona do pseudokodu i (2) ich standardowe biblioteki zapewniają przydatne struktury danych od razu po wyjęciu z pudełka (koncepcja akumulatorów, o której wspomniał @Robert). Dlatego korzystanie z nich jest całkowicie w porządku. Używaj tego, co maksymalizuje produktywność, zamiast wybierać język tylko dlatego, że jest to główny nurt lub „fajne”.


Jesteś hipsterem czy coś w tym stylu? Oto twój PBR. Mnie? Wolę być spoko.
Thomas Eding,

2

Podczas programowania w językach „wyższego poziomu” niż C / C ++ nie będziesz się uczyć, jak działa komputer. Nie będziesz w stanie opracowywać takich rzeczy, jak systemy wbudowane, systemy operacyjne i sterowniki sprzętowe. Znajomość C pomaga również w nauce asemblera.

Ponadto znaczna większość wszystkich systemów o kluczowym znaczeniu jest wciąż rozwijana w C, więc możesz nie być w stanie pracować w kilku gałęziach oprogramowania (lotnictwo / motoryzacja / technika medyczna itp.), Nie wiedząc o tym.


Pytanie dotyczyło wyraźnie algorytmów, a nie aspektów zbliżonych do metalu.
Konrad Rudolph

@KonradRudolph Dobrze, ale pisanie sterowników sprzętowych jest najczęściej bardzo ściśle związane z algorytmami. Na przykład, pisząc sterownik konwertera analogowo-cyfrowego, będziesz musiał opracować filtry cyfrowe, a być może także jakiś system kolejki lub systemu priorytetowego. A potem interfejs API na sterowniku. Jest bardzo podobny do pisania „obiektu” lub „abstrakcyjnego typu danych”.

@Lundin Dziękujemy za wspomnienie o wadach w rzeczywistym świecie.
ffledgling

1

Jeśli kiedykolwiek pojawia się pytanie dotyczące „wielkiej notacji O” i próbujesz to zmierzyć, może być trudniej zrobić w Pythonie, chyba że wiesz dużo więcej o tym, jak Python implementuje różne rzeczy, na przykład lista Python nie jest listą połączoną ; Sortowanie Pythonów to TimSort; Śmieci w języku Python są zbierane w określonych momentach ...

Zawsze łatwiej jest mi podłączyć program C do tego, co prawdopodobnie dzieje się na procesorze, ale nawet tutaj jest buforowanie procesora; podział czasu systemu operacyjnego; Optymalizacje kompilatora itp., Które mogą mieć wpływ na moją intuicję.

Szybsze jest pisanie i debugowanie kodu w Pythonie, więc kiedy mam wybór, najpierw piszę w Pythonie, koncentrując się na uzyskaniu czegoś, co zadziała. Dzięki temu działającemu programowi Python możesz często umieścić go w większym systemie i dowiedzieć się nie tylko, że działał, ale także czy był wystarczająco szybki lub pod jakim względem był wolny. Uzyskanie prawdziwych danych dotyczących wydajności pomaga wtedy zoptymalizować prędkość i pozwala przetestować wersję Pythona pod kątem późniejszych zapisów w Pythonie, C lub cokolwiek innego.

Wady używania samego Pythona polegają na tym, że czerpanie korzyści z algorytmów napisanych w oczekiwaniu na kompilację typu C do modelu procesora może być trudne. Wady korzystania z samego C są takie, jak powiedzieliście: świnia jest do pisania i debugowania, w wyniku czego zbyt często trzeba pisać własne biblioteki.

Myślę, że najlepiej byłoby używać ich obu (i innych języków), dopóki nie wyczujesz ich kompromisów. Sam byłem dobrym koderem C, ale teraz piszę bardzo mało oryginalnego kodu C, chociaż nadal muszę czytać (a czasem debugować) kod C w mojej pracy. Chociaż wolę Python, znam i nadal używam Perla i Awka (oraz sed, grep i sort oraz Tcl, C i ...).


Nie zgadzam się z pierwszym akapitem. Python kładzie duży nacisk na struktury danych i wyraźnie dokumentuje sposób implementacji predefiniowanych struktur danych. Oczywiście wyrzucanie elementów bezużytecznych spowoduje wypaczenie środowisk wykonawczych, ale rzadko wypacza porządek typu duże-O.
Konrad Rudolph,

1

Radziłbym ci spojrzeć na Scalę lub Clojure (ale użyj adnotacji typu). W niektórych przypadkach mogą być tak szybkie jak C, w innych są nadal znacznie szybsze niż Ruby / Python, a jednocześnie mają bardzo sumienie i wyraźną notację w przeciwieństwie do C ( IMHO ). Rozważ to vs kod C:

for (i <- 1 to 100; j <- 2 until 100;
     k <- 1 to 2; if i != j) {
     //...
}

Również mają programowania funkcyjnego arsenał podobnego do Ruby / Python map, filter, reduceitp, które nie jest tak szybki jak rekurencja Iteracja lub zadzwoń ogon, jednak jest to nadal znacznie szybciej niż te w pełni dynamicznych języków skryptowych.


1

Bardzo chciałbym usłyszeć od osób, które używały tych języków w branży / i / lub do opracowania dużego oprogramowania / bibliotek itp.

Przez kilka lat pracowałem nad małą częścią dużej biblioteki C ++ i napisałem pracę licencjacką i magisterską w kontekście tej biblioteki. Nawiasem mówiąc, biblioteka jest biblioteką algorytmów bioinformatycznych i struktur danych.

Biblioteka jest wbudowana w C ++, ponieważ C ++ jest prawie idealny do specyficznych wymagań tej biblioteki i ogólnie do bibliotek algorytmów. Gdybym miał opracować inną bibliotekę algorytmów, a wybór języka byłby mój, prawie na pewno wybrałbym ponownie C ++.

Powodem jest nie tylko wydajność, ale także mocny system typów, który przede wszystkim zapewnia większe bezpieczeństwo typów, a po drugie umożliwia typom dokumentowanie używanego algorytmu. Z mojego doświadczenia może to znacznie poprawić czytelność i łatwość konserwacji.

To powiedziawszy, w przypadku prostych bazgrołów algorytmicznych i łamigłówek prawie zawsze używam Pythona (głównie dlatego, że brzmi prawie jak pseudo kod), chyba że chcę wypróbować, jak najlepiej sformułować problem w C ++. Jak dotąd nie rozwiązałem wielu problemów z SPOJ lub TopCoder, więc nie wiem, czy wydajność jest tak istotna, że ​​użycie szybkiego języka jest kluczowe.

Ale zwykle liczy się poprawność algorytmu w celu jego zaliczenia. W takich przypadkach Python działa dobrze. Na przykład w przypadku problemów z Project Euler (które nie są określone w czasie, liczy się tylko prawidłowe rozwiązanie), Python jest doskonale dostosowany.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.