在算法编程方面,Python优于C


16

我一直在研究一些算法,并一直在研究SPOJ.pl TopCoder等网站。我发现程序员通常在大多数算法编程竞赛中都喜欢C或C ++。

现在,我最近遇到了一些麻烦。我对C和Python都了解一些,并且在尝试编写代码时,对于大多数算法,我似乎更喜欢Python而不是C。每当我坐下来写CI的代码时,大约15分钟后就放弃了,因为我觉得它太麻烦了并且倾向于使用python。传递矩阵指针等似乎浪费了我实际上可以用来思考算法本身的时间。

现在,我知道并且听到很多人说C是一种非常重要的语言,并且是许多程序员的后援。

我想知道的是,我的这种方法是否有任何缺点/后果/缺点等。

这不是Python与C的争论。从长远来看,这个关于易用性而不是C首选python的特定实践将如何影响我或任何其他程序员/计算机科学家的问题。


我很乐意听到在行业中使用过这些语言的人,以及/或者开发大型软件/库等的人。


没有连结此讨论这个话题将是不完整lukeplant.me.uk/blog/posts/...
permeakra

11
@permeakra:只是一声喧,基本上是说学习Haskell和Python并不能使您在其他语言中变得更好,因为其他语言很烂。
罗伯特·哈维

这不仅是花一现,还包含Python和Haskell如何影响用户思想的描述,以及其他人对该主题的许多评论。相比之下,它不使用c作为低级语言,但是使用了更高级别的语言,但是思想是相同的-人们开始将其他语言的思想带入他目前正在使用的语言中,从而使代码变得不习惯。这可能是一件好事,但是……
permeakra 2012年


不管它是什么,看到一些非算法编程都是很有趣的。
SK-logic

Answers:


14

以我的经验,当人们在用C语言编码算法时难度过大时,通常是因为他们将数据结构管理与算法紧密结合在一起,而不是创建适当的抽象。例如,在任何地方手动操作链接列表指针,而不要使用make push()pop()函数。他们太习惯了将这些抽象提供给他们。

尽管在较低级别的抽象中,此问题更为明显,但无论如何,未能识别紧密耦合并创建适当的抽象都是一个问题。在使用C语言之前,请练习这些技能,直到您可以使算法看起来清晰易读为止,然后再推广到您使用的任何语言。

我偶尔在python程序员中看到的另一个问题是难以适应大规模性能。当然,性能通常不是主要的考虑因素,但是在处理千兆字节或更多数据时,为相对较小的数据结构实现算法的最Python方式可能会使系统瘫痪。成为一名优秀的C程序员可以帮助您更加了解任何语言中的此类问题。

您可以用其他语言学习这些技能吗?当然可以,但是当您弄错它时,C可以使它更加明显。

话虽这么说,但是即使我很熟悉C,也可以选择使用python进行算法编程。Python的语言功能使其非常适合此类编程,并且性能差异通常可以忽略不计。我不能说为什么其他两个都选择C的程序员。我想他们中的很多人只是为了使自己与众不同而这样做。


1
“他们太习惯了将这些抽象提供给他们。” 这是否假设我在C之前学过python,因此无法适应或遵循这些原则?
2013年

10

主要兴趣不是编程的研究人员更喜欢诸如Python之类的高级语言,因为与C语言相比,他们可以使用此类语言更轻松地编写解决方案。Python特别适合于此,因为它更面向“原型”,它是“包括电池”,它与NumPy和SciPy等数字库集成。

如果研究人员需要更好的性能,则通常会将他们在Python中创建的算法移交给软件工程师,然后由软件工程师找到对其进行优化的方法(包括C语言进行重新编码)。


那么,基本上研究人员和软件工程师之间具有设计师手工艺人的关系吗?以及如何利用行业中这两种人?
2012年

9
我认为可以得出的结论是,用Python编码算法,然后用C编写更完善的实现是一种完全可以接受的方案。
罗伯特·哈维

或“用Cython编码”?
endlith 2014年

10

请记住,SPOJ.pl,ACM竞赛和所有类似竞赛都专注于快速生成可在竞赛后立即丢弃的工作代码。TopCoder可以这样做,但是范围较小(至少在OO设计级别上正确组织了代码)。

但是,在编程的现实世界中,您在算法编程竞赛中几乎每走一条捷径都是一种反模式。只有牢记这一点,您才能进行任何形式的比较。让我们举个例子:在不同的函数之间传递多维数组。在竞争环境中,最好的方法是简单地将数组声明为全局数组,以节省确定正确的呼叫详细信息的时间(例如,我应该传递大小,还是可以确定大小?)。在现实编程中,我会做相反的事情。

因此,对于您的问题,选择Python而不是C进行算法是否会产生复杂的后果,我会拒绝。如果您只对算法感兴趣,那么您将在Python和C中做相同的事情。以功能语言实现它可能会带来一些差异,但是算法仍然相同。

实际上,通过用C实现算法所获得的唯一一件事就是对执行的更多控制,并保证您仅使用较低级别的抽象。这不是一件小事,因为在Python中许多复杂性被隐藏了。但是,如果问题在高层抽象中并非微不足道,那么您可能只是失去了执行速度,而且在大多数情况下,您并没有真正尝试使程序尽可能快地运行,您只是在学习。

正如已经建议的那样,如果Python实在太慢,您总是可以将Python实现与C实现交换。但这在一个大型项目中可能会发生2-3次,因此从C语言开始可能会浪费时间,除非这是您选择的语言(并且您表示不是)。


1
如果正在编写一个真正的数学密集型应用程序,则几乎可以肯定会选择C或C ++(没有“ C / C ++”之类的东西),因为与任何解释语言相比,它的性能都有很大提高。我几年前看过Topcoder,回想起很多C ++大肆泄漏内存,因为比赛并不关心泄漏等次要细节。我没被打动。
Jim in Texas

正是我的观点。这是一个优先级问题:顶级编码器不在乎内存泄漏,因为内核无论如何都会清除它们。只要节省时间,他们就不会在意不良做法或反模式。
K.Steff

2
您的最后一段体现了黄金法则:“使之工作,然后使其快速”。
Carson63000

9

作为TopCoder的长期会员和SPOJ的偶尔用户,我可以告诉您,在竞赛中偏爱C / C ++而不是其他语言的主要原因是它的原始速度。当您的程序执行定时时,选择您能获得的“最快”语言将面临巨大压力,因为这会使您在算法编码方面更加懈怠。我在TC方面的发展从Java到C#再到C ++。

但是,这种情况在比赛中比在日常开发中更为常见:尽管编写最佳代码具有普遍意义,但尽快完成代码并使其尽可能易于维护的相对重要性通常比节省一些代码更为重要。一百个CPU周期。如果您更喜欢用Python编写代码,则通常是首选的解决方案。

而且,Python提供了C ++中没有的高级功能。构建它们通常非常昂贵,有时甚至是不可能的(例如,考虑使用C ++构建反射或自我修改代码)。在这种情况下,依赖高级语言也可能是最佳解决方案。


由于您是TC和SPOJ的用户。如果我们使用python作为代码,在时间和简单性之间的权衡是否很大?即如果可以使用C成功提交相同的算法,是否可以使用python成功提交?(是的,我知道它/可能会在很大程度上因问题而异,但是在大多数情况下还是仅在某些情况下会存在劣势?)
幼稚的2012年

@Ayos我不能代表Python,因为我从来没有在TC或SPOJ的上下文中使用过它,但是C ++相对于C#和Java的优势只是偶尔会变得很重要,即使如此,它也不是太重要。我只能记得一种情况,即已经用C ++编码到C#的算法的直接端口因超时而失败,但是它在练习室中。在大多数情况下,发现正确的算法是成功和失败提交之间唯一的区别。
dasblinkenlight 2012年

1
请注意,诸如Python,Ruby和Perl之类的解释语言的运行速度比诸如Java和C#(与C相比速度较慢)之类的已编译高级语言慢几倍。最终,除非您计划使用非常大的数据集或需要实时速度,否则这并不重要。
KChaloux 2012年

5

每当我坐下来写CI的代码时,大约15分钟后就放弃了,因为我觉得它太麻烦了并且倾向于使用python。

生产率的提高是C和C ++作业大量减少的常见原因。

从长远来看,这个关于易用性而不是C首选python的特定实践将如何影响我或任何其他程序员/计算机科学家的问题。

这有两个核心部分。首先是算法编程。您使用哪种语言来表达算法真的不重要。使用算法本身并将合适的算法适合合适的问题是关键部分,因此这里没有真正的问题。

第二部分是生产率的提高。使用使您的工作效率随着时间的推移而提高的习惯是一种好习惯,而在您的职业生涯中却无济于事的事情。能够用不同的语言表达算法是非常有帮助的,但是这种帮助更多地取决于语言使用的惯用法,而不一定是这些语言的含义。

简而言之,不用担心。用于表达算法的内容远没有能够表达它那么重要。


3
“ C和C ++作业已大大减少”。??正如我看到的相反趋势,这似乎是突如其来的。-1,直到您可以声明该语句的源。

3

使用Python或Ruby之类的高级语言的优势在于:(1)它们的语法非常接近伪代码;(2)它们的标准库提供了开箱即用的有用数据结构(@Robert提到的电池概念)。因此,更喜欢使用它们。使用任何东西都能最大化您的生产力,而不是仅仅因为它是主流或“酷”而选择一种语言。


您是时髦人士还是其他人?这是您的PBR。我?我宁愿很酷。
Thomas Eding

2

在使用比C / C ++更高的“高级”语言进行编程时,您会错过的是学习计算机的工作方式。您将无法开发嵌入式系统,操作系统和硬件驱动程序。学习汇编程序时,了解C也有帮助。

而且,所有关键任务系统中的绝大多数仍然是用C语言开发的,因此您可能无法在不知道的情况下在多个软件软件分支(航空航天/汽车/医疗技术等)中工作。


问题显然是关于算法的,而不是关于金属的方面。
康拉德·鲁道夫2012年

@KonradRudolph好的,但是编写硬件驱动程序通常与算法密切相关。例如,当编写用于模数转换器的驱动程序时,您将不得不开发数字滤波器,也许还需要开发某种队列或优先级系统。然后是驱动程序顶部的API。这与编写“对象”或“抽象数据类型”非常相似。

@Lundin感谢您提到现实世界场景中的缺点。
2012年

1

如果有关“大O表示法”的问题一直存在,并且您尝试对其进行衡量,那么除非您对python如何实现事情有更多的了解,例如,Python列表不是链接列表,否则在Python中很难做到这一点。 ; Python的排序方式是TimSort;Python垃圾会在特定时间收集...

我总是发现将C程序连接到处理器上可能发生的事情比较容易,但是即使在这里,也存在处理器缓存。操作系统的时间分片;编译器优化等会影响我的直觉。

我发现编写和调试Python代码更快,因此,在有选择的情况下,我将首先使用Python编写代码,专注于获得有用的东西。使用这个运行良好的Python程序,您通常可以将其放入更大的系统中,不仅可以发现它是否起作用,而且还可以发现它是否足够快或在什么方面变慢。然后,获取一些实际性能数据将有助于您优化速度,并允许您针对Python或C或更高版本中的任何后续重写测试Python版本。

因此,仅使用Python的弊端在于,要想获得期望在处理器模型上进行类似于C的编译的算法,可能很难获得其收益。正如您所言,仅使用C的缺点是:编写和调试它很麻烦,最终您不得不过于频繁地编写自己的库。

我认为最好同时使用它们(和其他语言),直到您了解它们之间的取舍。我本人是一位优秀的C程序员,但现在我只编写了很少的原始C代码,尽管我在工作中仍然必须阅读(有时是调试)C代码。尽管我更喜欢Python,但我知道并且仍然使用Perl和Awk(以及sed和grep和sort以及Tcl和C和...)。


我不同意第一段。Python非常重视数据结构,并清楚地记录了如何实现预定义的数据结构。当然,垃圾回收会扭曲运行时,但很少会扭曲big-O顺序。
康拉德·鲁道夫2012年

1

我建议您查看Scala或Clojure(但使用类型注释)。在某些情况下,它们的速度可以与C一样快,在其他情况下,它们的速度仍 Ruby / Python快得多,并且与C(IMHO)相比,它具有非常简洁的符号。考虑一下此vs C代码:

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

此外,他们也有类似Ruby的/ Python的函数编程库mapfilterreduce等,这是不一样快迭代或尾递归调用,但它仍然是快得多则完全动态脚本语言。


1

我很乐意听到在行业中使用过这些语言的人,以及/或者开发大型软件/库等的人。

我已经在大型C ++库的一小部分上工作了几年,并在该库的背景下写了我的学士和硕士学位论文。顺便说一句,该库是用于生物信息学算法和数据结构的库。

该库是用C ++构建的,因为C ++几乎可以完美满足该库的特定要求以及一般的算法库。如果我要开发另一个算法库并且选择语言是我的话,那么我几乎肯定会再次选择C ++。

原因不仅在于性能,还在于强大的类型系统,它首先为您提供了更多的类型安全性,其次还使您能够让您的类型记录所使用的算法。(根据我的经验)这可以大大提高可读性和可维护性。

就是说,对于简单的算法涂鸦和难题,我几乎总是使用Python(主要是因为是的,它读取的几乎类似于伪代码),除非我特别想尝试如何最好地用C ++提出问题。到目前为止,我还没有解决许多SPOJ或TopCoder问题,所以我不知道那里的性能是否真的如此关键,以至于使用快速语言至关重要。

但是通常重要的是使算法正确通过。在这种情况下,Python可以正常工作。例如,对于Project Euler问题(没有计时,只有正确的解决方案很重要),Python非常适合。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.