scala与python区别都有哪些

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala与python区别都有哪些相关的知识,希望对你有一定的参考价值。

Scala是一门多范式的编程语言,一种类似java的编程语言,设计初衷是实现可伸缩的语言、并集成面向对象编程和函数式编程的各种特性。Python

参考技术A

Scala是一门多范式的编程语言,一种类似java的编程语言,设计初衷是实现可伸缩的语言、并集成面向对象编程和函数式编程的各种特性。

Python是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。Python的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。

scala与Python的区别:

1、性能对比

由于Scala是基于JVM的数据分析和处理,Scala比Python快10倍。当编写Python代码用且调用Spark库时,性能是平庸的,但如果程序涉及到比Python编码还要多的处理时,则要比Scala等效代码慢得多。Python解释器PyPy内置一个JIT(及时)编译器,它很快,但它不提供各种Python C扩展支持。在这样的情况下,对库的C扩展CPython解释器优于PyPy解释器。

使用Python在Spark的性能开销超过Scala,但其重要性取决于您在做什么。当内核数量较少时,Scala比Python快。随着核数的增加,Scala的性能优势开始缩小。

当大量的处理其工作时,性能不是选择编程语言的主要驱动因素。然而,当有重要的处理逻辑时,性能是一个主要因素,Scala绝对比Python提供更好的性能,用于针对Spark程序。

相关推荐:《Python基础教程》

2、学习曲线

在用Scala语言编写Spark程序时有几个语法糖,所以大数据专业人员在学习Spark时需要非常小心。程序员可能会发现Scala语法有时会让人发疯。Scala中的一些库很难定义随机的符号运算符,而这些代码可以由没有经验的程序员理解。在使用Scala时,开发人员需要关注代码的可读性。与Scala相比,Java或Python是一个灵活的语法复杂的语言。对Scala开发人员的需求越来越大,因为大数据公司重视能在Spark中掌握数据分析和处理的高效而健壮的开发人员。

Python是为Java程序员学习相对容易的因为它的语法和标准库。然而,Python是不是一个高度并行和可扩展的像SoundCloud或推特系统的理想选择。

学习Scala丰富了程序员对类型系统中各种新抽象的认识,新的函数编程特性和不可变数据。

3、并发性

大数据系统的复杂多样的基础结构需要一种编程语言,它有能力集成多个数据库和服务。在大数据的生态系统中,Scala胜在Play框架提供了许多异步库和容易集成的各种并发原语,比如Akka。Scala使开发人员编写高效的、可读性和可维护性的服务而不是。相反,Python不支持的重量级进程并行在用uWSGI时,但它不支持真正的多线程。

当使用Python写Spark程序时,不管进程有多少线程,每次只有一个CPU在Python进程中处于活动状态。这有助于每个CPU核心只处理一个进程,但糟糕的是,每当部署新代码时,需要重新启动更多的进程,还需要额外的内存开销。Scala在这些方面更高效,更容易共事。

4、类型安全

当用Spark编程时,开发人员需要根据变化的需求不断地重新编码代码。Scala是静态类型语言,尽管它看起来像一种动态类型语言,因为它具有优雅的类型推断机制。作为静态类型语言,Scala仍然提供编译器来捕获编译时错误。

重构像Scala这样的静态类型语言的程序代码比重构像Python这样的动态语言代码要容易得多且简单。开发人员在修改Python程序代码后常常会遇到困难,因为它造成的bug比修复程序原有的bug要多。所以最好是缓慢而安全地使用Scala,而不是快速的、死地使用Python。

对于小型的特殊实验,Python是一种有效的选择,但它并不像静态语言那样有效地扩展到大型软件工程中。

5、易用性

Scala和Python语言在Sparkcontext中有同样的表达,因此通过使用Scala或Python可以实现所需的功能。无论哪种方式,程序员都会创建一个Sparkcontext并调用函数。Python是一种比Scala更便于用户使用的语言。Python不那么冗长,开发人员很容易用Python编写脚本来调用Spark。易用性是一个主观因素,因为它取决于程序员的个人偏好。

6、高级特性

Scala编程语言有几个存在类型、宏和隐式。Scala的晦涩难懂的语法可能很难对开发人员可能无法理解的高级特性进行实验。然而,Scala的优势在于在重要的框架和库中使用这些强大的特性。

话虽如此,Scala没有足够的数据科学工具和库,如Python用于机器学习和自然语言处理。Sparkmlib–机器学习库只有较少的ML算法但他们是理想的大数据处理。Scala缺乏良好的可视化和本地数据转换。Scala无疑是Spark streaming特性的最佳选择,因为Python 通过pySpark 调用Spark.streaming不像Scala那样先进和成熟。

总结

“Scala速度更快,使用方便 但上手难,而Python则较慢,但很容易使用。”

Spark框架是用Scala编写的,所以了解Scala编程语言有助于大数据开发人员轻松地挖掘源代码,如果某些功能不能像预期的那样发挥作用。使用Python增加了更多问题和bug的可能性,因为2种不同语言之间的转换是困难的。为Spark使用Scala提供对Spark框架的最新特性的访问,因为它们首先在Scala中可用,然后移植到Python中。

根据Spark决定Scala和Python取决于最适合项目需要的特性,因为每种语言都有自己的优点和缺点。在使用Apache Spark编程语言之前,开发者必须学习Scala和Python来熟悉它们的特性。学习了Python和Scala之后,决定何时使用Scala来Spark以及何时使用Python来调用Spark是相当容易的。Apache Spark编程语言的选择完全取决于要解决的问题。

Scala 都有哪些自动资源管理替代方案?

【中文标题】Scala 都有哪些自动资源管理替代方案?【英文标题】:What Automatic Resource Management alternatives exist for Scala?Scala 有哪些自动资源管理替代方案? 【发布时间】:2011-01-13 12:37:55 【问题描述】:

我在网上看到了很多 Scala 的 ARM(自动资源管理)示例。写一个似乎是一种仪式,尽管大多数看起来很像。不过,我确实看到了一个使用延续的非常酷的示例。

无论如何,很多代码都有某种类型的缺陷,所以我认为在 Stack Overflow 上有一个参考是一个好主意,我们可以在这里投票选出最正确和最合适的版本。

【问题讨论】:

如果不是社区 wiki,这个问题会产生更多答案吗?请注意是否在社区 wiki 奖励声誉中投票答案... 唯一引用可以为 ARM 添加另一个安全级别,以确保在调用 close() 之前将资源引用返回给管理器。 thread.gmane.org/gmane.comp.lang.scala/19160/focus=19168 @retronym 我认为唯一性插件将是一场革命,而不是延续。而且,事实上,我认为这是 Scala 中的一件事,它很可能会在不久的将来被移植到其他语言。当它出现时,让我们确保相应地编辑答案。 :-) 因为我需要能够嵌套多个 java.lang.AutoCloseable 实例,每个实例都依赖于前一个成功实例化的实例,所以我终于找到了一个对我非常有用的模式。我把它写成类似 *** 问题的答案:***.com/a/34277491/501113 【参考方案1】:

Chris Hansen 的 blog entry 'ARM Blocks in Scala: Revisited' from 3/26/09 谈到了 Martin Odersky 的 FOSDEM presentation 的幻灯片 21。下一个块直接取自幻灯片 21(经许可):

def using[T <:  def close() ]
    (resource: T)
    (block: T => Unit) 

  try 
    block(resource)
   finally 
    if (resource != null) resource.close()
  

--结束报价--

那么我们可以这样调用:

using(new BufferedReader(new FileReader("file")))  r =>
  var count = 0
  while (r.readLine != null) count += 1
  println(count)

这种方法有什么缺点?这种模式似乎可以解决我需要自动资源管理的 95%...

编辑:添加代码sn-p


Edit2:扩展设计模式 - 从 python with 语句和寻址中获取灵感:

在块之前运行的语句 根据托管资源重新抛出异常 用一个 using 语句处理两个资源 通过提供隐式转换和Managed 类进行资源特定处理

这是 Scala 2.8。

trait Managed[T] 
  def onEnter(): T
  def onExit(t:Throwable = null): Unit
  def attempt(block: => Unit): Unit = 
    try  block  finally 
  


def using[T <: Any](managed: Managed[T])(block: T => Unit) 
  val resource = managed.onEnter()
  var exception = false
  try  block(resource)  catch  
    case t:Throwable => exception = true; managed.onExit(t)
   finally 
    if (!exception) managed.onExit()
  


def using[T <: Any, U <: Any]
    (managed1: Managed[T], managed2: Managed[U])
    (block: T => U => Unit) 
  using[T](managed1)  r =>
    using[U](managed2)  s => block(r)(s) 
  


class ManagedOS(out:OutputStream) extends Managed[OutputStream] 
  def onEnter(): OutputStream = out
  def onExit(t:Throwable = null): Unit = 
    attempt(out.close())
    if (t != null) throw t
  

class ManagedIS(in:InputStream) extends Managed[InputStream] 
  def onEnter(): InputStream = in
  def onExit(t:Throwable = null): Unit = 
    attempt(in.close())
    if (t != null) throw t
  


implicit def os2managed(out:OutputStream): Managed[OutputStream] = 
  return new ManagedOS(out)

implicit def is2managed(in:InputStream): Managed[InputStream] = 
  return new ManagedIS(in)


def main(args:Array[String]): Unit = 
  using(new FileInputStream("foo.txt"), new FileOutputStream("bar.txt"))  
    in => out =>
    Iterator continually  in.read()  takeWhile( _ != -1) foreach  
      out.write(_) 
    
  

【讨论】:

还有其他选择,但我并不是要暗示这有什么问题。我只想在 Stack Overflow 上找到所有这些答案。 :-) 你知道标准API中是否有这样的东西吗?一直为自己写这个似乎是件苦差事。 自此发布以来已经有一段时间了,但是如果 out 构造函数抛出,第一个解决方案不会关闭内部流,这可能不会在这里发生,但在其他情况下这可能会很糟糕。 close 也可以抛出。致命异常之间也没有区别。第二个到处都有代码气味,比第一个优势为零。您甚至会丢失实际类型,因此对于 ZipInputStream 之类的东西将毫无用处。 如果块返回迭代器,您建议如何执行此操作?【参考方案2】:

丹尼尔,

我最近刚刚部署了用于自动资源管理的 scala-arm 库。你可以在这里找到文档:https://github.com/jsuereth/scala-arm/wiki

这个库支持三种使用方式(目前):

1) 命令式/for-表达式:

import resource._
for(input <- managed(new FileInputStream("test.txt")) 
// Code that uses the input as a FileInputStream

2) 单子风格

import resource._
import java.io._
val lines = for  input <- managed(new FileInputStream("test.txt"))
                  val bufferedReader = new BufferedReader(new InputStreamReader(input)) 
                  line <- makeBufferedReaderLineIterator(bufferedReader)
                 yield line.trim()
lines foreach println

3) 定界延续样式

这是一个“echo”tcp 服务器:

import java.io._
import util.continuations._
import resource._
def each_line_from(r : BufferedReader) : String @suspendable =
  shift  k =>
    var line = r.readLine
    while(line != null) 
      k(line)
      line = r.readLine
    
  
reset 
  val server = managed(new ServerSocket(8007)) !
  while(true) 
    // This reset is not needed, however the  below denotes a "flow" of execution that can be deferred.
    // One can envision an asynchronous execuction model that would support the exact same semantics as below.
    reset 
      val connection = managed(server.accept) !
      val output = managed(connection.getOutputStream) !
      val input = managed(connection.getInputStream) !
      val writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output)))
      val reader = new BufferedReader(new InputStreamReader(input))
      writer.println(each_line_from(reader))
      writer.flush()
    
  

代码使用资源类型特征,因此它能够适应大多数资源类型。它有一个回退,可以通过 close 或 dispose 方法对类使用结构类型。请查看文档,如果您想添加任何方便的功能,请告诉我。

【讨论】:

是的,我看到了。我想看一下代码,看看你是如何完成一些事情的,但我现在太忙了。无论如何,由于问题的目标是提供对可靠 ARM 代码的参考,因此我将其作为公认的答案。【参考方案3】:

这是使用延续的James Iry 解决方案:

// standard using block definition
def using[X <: def close(), A](resource : X)(f : X => A) = 
   try 
     f(resource)
    finally 
     resource.close()
   


// A DC version of 'using' 
def resource[X <: def close(), B](res : X) = shift(using[X, B](res))

// some sugar for reset
def withResources[A, C](x : => A @cps[A, C]) = resetx

以下是用于比较的带有和不带有延续的解决方案:

def copyFileCPS = using(new BufferedReader(new FileReader("test.txt"))) 
  reader => 
   using(new BufferedWriter(new FileWriter("test_copy.txt"))) 
      writer => 
        var line = reader.readLine
        var count = 0
        while (line != null) 
          count += 1
          writer.write(line)
          writer.newLine
          line = reader.readLine
        
        count
      
    
  


def copyFileDC = withResources 
  val reader = resource[BufferedReader,Int](new BufferedReader(new FileReader("test.txt")))
  val writer = resource[BufferedWriter,Int](new BufferedWriter(new FileWriter("test_copy.txt")))
  var line = reader.readLine
  var count = 0
  while(line != null) 
    count += 1
    writer write line
    writer.newLine
    line = reader.readLine
  
  count

Tiark Rompf 的改进建议如下:

trait ContextType[B]
def forceContextType[B]: ContextType[B] = null

// A DC version of 'using'
def resource[X <: def close(), B: ContextType](res : X): X @cps[B,B] = shift(using[X, B](res))

// some sugar for reset
def withResources[A](x : => A @cps[A, A]) = resetx

// and now use our new lib
def copyFileDC = withResources 
 implicit val _ = forceContextType[Int]
 val reader = resource(new BufferedReader(new FileReader("test.txt")))
 val writer = resource(new BufferedWriter(new FileWriter("test_copy.txt")))
 var line = reader.readLine
 var count = 0
 while(line != null) 
   count += 1
   writer write line
   writer.newLine
   line = reader.readLine
 
 count

【讨论】:

Doesn't using(new BufferedWriter(new FileWriter("test_copy.txt"))) 在 BufferedWriter 构造函数失败时遇到问题?每个资源都应该包装在 using 块中... @Jaap 这是suggested by Oracle 的风格。 BufferedWriter 不会抛出已检查的异常,因此如果抛出任何异常,程序预计不会从中恢复。【参考方案4】:

目前Scala 2.13 终于支持:try with resources 使用 Using :),示例:

val lines: Try[Seq[String]] =
  Using(new BufferedReader(new FileReader("file.txt")))  reader =>
    Iterator.unfold(())(_ => Option(reader.readLine()).map(_ -> ())).toList
  

或使用Using.resource避免Try

val lines: Seq[String] =
  Using.resource(new BufferedReader(new FileReader("file.txt")))  reader =>
    Iterator.unfold(())(_ => Option(reader.readLine()).map(_ -> ())).toList
  

您可以从Using doc 中找到更多示例。

用于执行自动资源管理的实用程序。它可用于执行使用资源的操作,然后以与创建资源相反的顺序释放资源。

【讨论】:

能否也添加Using.resource 变体? @DanielC.Sobral,当然,刚刚添加。 你会如何为 Scala 2.12 编写这个?这是一个类似的using 方法:def using[A &lt;: AutoCloseable, B](resource: A) (block: A =&gt; B): B = try block(resource) finally resource.close()【参考方案5】:

我看到了在 Scala 中进行 ARM 的逐步演进 4 步:

    没有 ARM:污垢 仅闭包:更好,但有多个嵌套块 Continuation Monad:使用 For 将嵌套变平,但不自然地分隔为 2 个块 直接风格延续:Nirava,啊哈!这也是最类型安全的替代方案:withResource 块之外的资源将出现类型错误。

【讨论】:

请注意,Scala 中的 CPS 是通过 monad 实现的。 :-) Mushtaq, 3) 您可以在不是 continuation 的 monad 的 monad 中进行资源管理 4) 使用我的 withResources/resource 分隔的 continuations 代码进行资源管理不再是(也不少于)类型安全而不是“使用”。仍然可能忘记管理需要它的资源。比较 using(new Resource()) first => val second = new Resource() //哎呀! // 使用资源 // 只有第一次被关闭 withResources val first = resource(new Resource()) val second = new Resource() // 哎呀! // 使用资源... // 只有第一次被关闭 Daniel,Scala 中的 CPS 就像任何函数式语言中的 CPS。它是使用 monad 的分隔延续。 詹姆斯,谢谢你的解释。坐在印度,我只希望我在那儿听你的 BASE 演讲。等着看你什么时候把这些幻灯片放到网上:)【参考方案6】:

更好的文件中包含轻量级(10 行代码)ARM。见:https://github.com/pathikrit/better-files#lightweight-arm

import better.files._
for 
  in <- inputStream.autoClosed
  out <- outputStream.autoClosed
 in.pipeTo(out)
// The input and output streams are auto-closed once out of scope

如果您不想要整个库,以下是它的实现方式:

  type Closeable = 
    def close(): Unit
  

  type ManagedResource[A <: Closeable] = Traversable[A]

  implicit class CloseableOps[A <: Closeable](resource: A)         
    def autoClosed: ManagedResource[A] = new Traversable[A] 
      override def foreach[U](f: A => U) = try 
        f(resource)
       finally 
        resource.close()
      
    
  

【讨论】:

这很不错。我采用了与这种方法类似的方法,但为 CloseableOps 而不是 foreach 定义了 mapflatMap 方法,以便理解不会产生可遍历。【参考方案7】:

如何使用 Type 类

trait GenericDisposable[-T] 
   def dispose(v:T):Unit

...

def using[T,U](r:T)(block:T => U)(implicit disp:GenericDisposable[T]):U = try 
   block(r)
 finally  
   Option(r).foreach  r => disp.dispose(r)  

【讨论】:

【参考方案8】:

另一种选择是 Choppy 的 Lazy TryClose monad。数据库连接非常好:

val ds = new JdbcDataSource()
val output = for 
  conn  <- TryClose(ds.getConnection())
  ps    <- TryClose(conn.prepareStatement("select * from MyTable"))
  rs    <- TryClose.wrap(ps.executeQuery())
 yield wrap(extractResult(rs))

// Note that Nothing will actually be done until 'resolve' is called
output.resolve match 
    case Success(result) => // Do something
    case Failure(e) =>      // Handle Stuff

还有流:

val output = for 
  outputStream      <- TryClose(new ByteArrayOutputStream())
  gzipOutputStream  <- TryClose(new GZIPOutputStream(outputStream))
  _                 <- TryClose.wrap(gzipOutputStream.write(content))
 yield wrap(gzipOutputStream.flush(); outputStream.toByteArray)

output.resolve.unwrap match 
  case Success(bytes) => // process result
  case Failure(e) => // handle exception

更多信息在这里:https://github.com/choppythelumberjack/tryclose

【讨论】:

【参考方案9】:

这是@chengpohi 的答案,经过修改,它适用于 Scala 2.8+,而不仅仅是 Scala 2.13(是的,它也适用于 Scala 2.13):

def unfold[A, S](start: S)(op: S => Option[(A, S)]): List[A] =
  Iterator
    .iterate(op(start))(_.flatMap case (_, s) => op(s) )
    .map(_.map(_._1))
    .takeWhile(_.isDefined)
    .flatten
    .toList

def using[A <: AutoCloseable, B](resource: A)
                                (block: A => B): B =
  try block(resource) finally resource.close()

val lines: Seq[String] =
  using(new BufferedReader(new FileReader("file.txt")))  reader =>
    unfold(())(_ => Option(reader.readLine()).map(_ -> ())).toList
  

【讨论】:

【参考方案10】:

虽然Using 可以,但我更喜欢单子风格的资源组合。 Twitter Util 的 Managed 非常好,除了它的依赖项和不太完善的 API。

为此,我为 Scala 2.12、2.13 和 3.0.0 发布了 https://github.com/dvgica/managerial。很大程度上基于 Twitter Util Managed 代码,没有依赖关系,一些 API 改进受到猫效应 Resource 的启发。

简单的例子:

import ca.dvgi.managerial._
val fileContents = Managed.from(scala.io.Source.fromFile("file.txt")).use(_.mkString)

但图书馆的真正实力是composing resources via for comprehensions。

让我知道你的想法!

【讨论】:

以上是关于scala与python区别都有哪些的主要内容,如果未能解决你的问题,请参考以下文章

python字典和列表区别都有哪些

scala与java的区别

scala与java的区别

Zuul与Gateway都有哪些区别

SQL Server 和 Oracle 以及 MySQL 都有哪些区别

CSS3与CSS的区别都有哪些