【翻譯】使用Swift語言來進行數(shù)據(jù)科學研究的指南

這篇文章首先發(fā)布在我的博客上:https://www.codewoody.com/posts/37730

Swift是蘋果公司研發(fā)的用來取代Objective C進行蘋果生態(tài)系統(tǒng)下軟件開發(fā)的語言膜宋。而且蘋果對于Swift的野心不至于一款A(yù)PP專用的開發(fā)語言而已。
從Swfit語言發(fā)布以來,蘋果公司就將Swift開源局扶,并且在Swift版本迭代過程中積極聽取來自普通開發(fā)者的意見征炼。蘋果致力于將Swift打造成跨平臺的
通用變成語言肛炮。我從Swfit發(fā)布起就開始使用了厚棵,當時接觸Swift的時候就為其所吸引烤宙,其引入的很多特性二汛,如Type Interference婿崭, Optional,以及
簡潔的語言形式等等肴颊,都能搞大大提高生產(chǎn)效率氓栈,并且提高程序的可讀性。

現(xiàn)在我已經(jīng)不怎么做iOS的開發(fā)的婿着,用Swift也偏少授瘦。這兩天突然看到了一篇名為A Comprehensive Guide to Learn Swift from Scratch for Data Science的文章,便想立刻通讀一遍竟宋,也許在之后我可以多用Swift來做研究方面的內(nèi)容提完。

Overview

  • Swift很快就成為了最為強大和有效的數(shù)據(jù)科學變成語言之一;
  • Swift和Python比較類似丘侠,因此你可以很容易地遷移到Swift上徒欣;
  • 這里我們將會涉及Swift的基礎(chǔ)知識,并學會如何快速搭建第一個數(shù)據(jù)科學模型蜗字;

簡介

Python在數(shù)據(jù)科學的領(lǐng)域的火熱程度自然不用多少打肝,各種各樣的排名和調(diào)查都將Python列為數(shù)據(jù)科學編程語言的佼佼者。

Python本身是非常靈活的挪捕,作為動態(tài)語言粗梭,你在使用Python不太需要遵守很多變成方面的潛規(guī)則,這帶來很大的靈活性级零。不過這導致隨著項目復(fù)雜度的增長断医,維護Python項目會變得比較困難。當然妄讯,性能也是一個重要的因素孩锡。一般腳本級別的數(shù)據(jù)科學應(yīng)用,Python的性能并不突出亥贸,Python一般被用來當做膠水語言躬窜,主要的計算一般是其他語言實現(xiàn)的模塊來完成。不過復(fù)雜項目中Python的性能還是會成為一個瓶頸炕置。

不過要記住的一點是荣挨,數(shù)據(jù)科學是一個含義廣泛且不斷演化的學科男韧。因此其使用的語言也要不斷演化。還記得R語言在數(shù)據(jù)科學中扮演老大角色的日子嗎默垄?與Python同時興起的還有Julia語言此虑。

沒錯,這里我們就要來討論一下將Swift語言應(yīng)用到數(shù)據(jù)科學中口锭。

image

“I always hope that when I start looking at a new language, there will be some mind-opening new ideas to find, and Swift definitely doesn’t disappoint. Swift tries to be expressive, flexible, concise, safe, easy to use, and fast. Most languages compromise significantly in at least one of these areas.” – Jeremy Howard

Jeremy Howard【~Howard was the President and Chief Scientist at Kaggle】為一個語言背書朦前,且將這門語言應(yīng)用到他的日常數(shù)據(jù)科學研究中時,你就應(yīng)該暫時停止你手上的工作好好聽一聽了鹃操。

在這這篇文章中我們將學習Swift編程語言韭寸,以及如何將其應(yīng)用到數(shù)據(jù)科學領(lǐng)域中【~原作者真啰嗦】。如果你是Python用戶荆隘,你會發(fā)現(xiàn)Swift和Python之間有很多的相似性恩伺。

Why Swift?

<i>“PyTorch was created to overcome the gaps in Tensorflow. FastAI was built to fill gaps in tooling for PyTorch. But now we’re hitting the limits of Python, and Swift has the potential to bridge this gap” </i>
<p style="text-align: right"><i>– Jeremy Howard</i></p>

今年來數(shù)據(jù)科學領(lǐng)域?qū)τ赟wift的興趣日漸增長,幾乎人人都在討論這個話題椰拒。以下是你要學習Swfit語言的幾個原因:

  • Swift很快晶渠,幾乎接近C語言的水平;
  • 與此同時燃观,Swift語言非常簡潔褒脯,可讀性很高。這和Python類似仪壮『┑撸【~個人認為Swift的可讀性可比Python高多了】;
struct MyModel: Layer {
  var conv = Conv2D<Float>(filterShaper: (5, 5, 3, 6))
  var pool = MaxPool2D<Float>(2)
  var flatten = Flatten<Float>()
  var dense = Dense<Float>(16 * 5 * 5, 10)
  
  @differentiable
  func call(_ input: Tensor<Float>) -> Tensor<Float> {
    return dense(flatten(pool(conv(input))))
  }
}
class MyModel(nn.Model):
  def __init__(self):
    super().__init__()
    self.conv = nn.Conv2d(3, 6, kernal_size=5)
    self.pool = nn.MaxPool2d(2)
    self.flatten = Flatten()
    self.dense = nn.Linear(16 * 5 * 5, 10)
  
  def forward(self, input):
    return self.dense(self.flatten(self.pool(self.conv(input))))
  • 相比于Python积锅,Swift是一門更高效爽彤,穩(wěn)定,安全的編程的語言缚陷;
  • Swift更適合應(yīng)用到移動應(yīng)用場景适篙。Swift是iOS的官方變成語言;
  • Swift對于自動微分操作支持非常好箫爷,因此非常適合數(shù)值計算【~參見上面的@differentiable】嚷节;
  • Swift背后有Google,Apple和FastAI的支持

下面這個視頻是Jeremy Howard談?wù)揝wift的優(yōu)勢的視頻。

<iframe width="560" height="315" src="https://www.youtube.com/embed/drSpCwDFwnM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Swift Basic for Data Analysis

在我們開始將Swift應(yīng)用于數(shù)據(jù)科學研究之前,我們先來學習一下Swift語言的基礎(chǔ)只是等缀。

Swift生態(tài)

目前Swift的數(shù)據(jù)科學應(yīng)用生態(tài)主要由兩個生態(tài)系統(tǒng)組成:

  1. 開源生態(tài)
  2. 蘋果生態(tài)
image

在開源生態(tài)系統(tǒng)中墙懂,我們可以在任何操作系統(tǒng)下載并運行swift憎茂。我們可以使用一些非常酷的Swift庫來構(gòu)建機器學習應(yīng)用,例如Swift for Tensorflow, SwiftAI以及SwiftPlot.

Swift也能讓我們無縫地從Python中引入成熟的數(shù)據(jù)科學庫雹食,例如Numpy, pandas, matplotlib以及scikit-learn缓屠。所以如果你之前還在擔心從Python遷移到Swift上有任何無法逾越的障礙的話奇昙,現(xiàn)在你可以寬心了。

另一方面敌完,蘋果公司的生態(tài)系統(tǒng)也有其優(yōu)勢储耐。蘋果公司提供了一些有用的庫,如CoreML滨溉,讓我們能夠在Python中訓練大型的模型并且直接導入到Swift中應(yīng)用什湘。另外,其中還包括了一些已經(jīng)提前訓練好了的成熟模型晦攒,我們可以直接在iOS和macOS應(yīng)用中使用禽炬。

image

還有一些其他的有意思的庫,比如Swift-CoreML-Transformers勤家,可以讓我們在iPhone上使用業(yè)界最新的文字生成模型,例如GPT-2, BERT等柳恐。

<i>There are multiple differences between the two ecosystems. But the most important one is that in order to use the Apple ecosystem, you need to have an Apple machine to work on and you can only build for Apple devices like the iOS, macOS etc.</i>

現(xiàn)在你對Swift有了一個宏觀的了解了伐脖,下面我們來走進代碼。

準備Swift環(huán)境

在Google Colab【~Colaboratory 是一個免費的 Jupyter 筆記本環(huán)境乐设,不需要進行任何設(shè)置就可以使用讼庇,并且完全在云端運行】上提供了支持GPU和TPU的Swift版本,這里我們直接使用這一服務(wù)近尚,從而省去安裝過程蠕啄。

<img src="https://imgs.codewoody.com/uploads/big/451eba98fbef8b87bf2473971390e66f.png" alt="" style="width: 60%"/>

你可以遵循下面的步驟創(chuàng)建一個啟用了Colab notebook。

  1. 打開一個空白的Swift notebook;
  2. 點擊"File"戈锻,然后選擇"Save a copy in Drive" - 這會將Swift notebook保存到你的Google Drive里面歼跟。
  3. 到這里我們就可以在Colab里面使用Swift了。我們來寫下第一行代碼:
print("hello world from Swift")

這就是Swift的hello world程序了格遭!接下來如果你想在本地運行Swift哈街,你可以按照如下的鏈接進行操作:

  1. Swift安裝指南:install instructions
  2. 要在Ubuntu中安裝Jupyter Notebook:[Jeremy Howard's instructions to install Swift]拒迅;
  3. 在Ubuntu上也可以使用Docker來安裝Swift:Swift for Docker

如果在macOS下面骚秦,直接從應(yīng)用商店安裝xcode就行,可以創(chuàng)建一個Swift Playground來試試Swift語言的特性璧微。我記得iPad上也有Swift Playground的應(yīng)用作箍。

接下來讓我們快速過一下Swift的基本語言特性。

The Print function

hello world程序中前硫,print函數(shù)的形式一點都不陌生啦胞得。

print("Swift is easy to learn!")

Variable in Swift

Swift提供了兩個創(chuàng)建變量的選項:letvar。其中let被用來創(chuàng)建常量开瞭,常量的值在其聲明周期中是不能被改變的懒震。var用來創(chuàng)建變量罩息,這意味著類似在Python里一樣,你可以修改變量的值个扰。

我們來看下面的例子瓷炮。創(chuàng)建兩個變量:

let a = "Analytics"
var b = "Vidhya"

讓我們來嘗試修改其值:

b = "AV"
a = "AV"

我們可以看到修改a的值時會出現(xiàn)錯誤:

Colab上的截圖

這種支持創(chuàng)建常量的能力可以幫助我們消除很多潛在bug。后面你可以看到我們會用let來創(chuàng)建那些非常重要且我們不希望修改的值递宅。例如訓練數(shù)據(jù)和結(jié)果我們會用let來創(chuàng)建娘香,而一些臨時變量會使用var來創(chuàng)建。

Swift的另一個很酷的特性是你可以使用emoji來作為變量名【~其實就是對Unicode的支持】

image

我們也可以使用希臘字母來作為變量名稱:

var π = 3.1415925

Swift數(shù)據(jù)類型

Swift支持一些通用的類型办龄,如整型烘绽,字符串,單精度浮點數(shù)(Float)和雙精度浮點數(shù)(Double)俐填。在創(chuàng)建變量時安接,Swift會根據(jù)初始化值自動推斷變量的類型。

let marks = 63
let percentage = 70.0
let name = "Sushil"

在創(chuàng)建變量時你也可以顯式的聲明變量類型英融。如果初始化值和聲明的類型不同盏檐,Swift會拋出錯誤。

let weight: Double = 62.8

字符串格式化的方式在Swift中非常簡潔驶悟。只需要用反斜杠\后面跟上括號就可以了:

let no_of_apples = 3
print("I have \(no_of_apples) apples")

你可以使用連續(xù)的三個雙引號"""來創(chuàng)建多行字符串胡野。

列表和字典(List and Dictionaries)

如同Python里面一樣,Swift里面也支持List和Dictionary數(shù)據(jù)結(jié)構(gòu)痕鳍。不同于Python硫豆,在Swift中這兩種類型都使用方括號[]

var shoppingList = ["catfish", "water", "tulip", "blue paint"]
shoppingList[1] = "bottle of water"

var occupationsDist = [
  "Malcolm": "Caption",
  "Kaylee": "Mechanic"
]

ccupationsDict["Jayne"] = "Public Relations"

循環(huán)

除了支持經(jīng)典的循環(huán)之外笼呆,Swift有一些自定義的比較獨特的循環(huán)形式:

for...in loop

類似Python的寫法熊响,在Swift中,你可以以如下形式來遍歷列表Lists或者ranges

for i in 0...5 {
  print(i)
}

var someList = [20, 30, 10, 40]
for item in someList {
  print(item * 2)
}

上面的連續(xù)三個點的符號用來創(chuàng)建ranges诗赌。...創(chuàng)建的兩側(cè)是閉集耘眨, 如果要創(chuàng)建不包含最右側(cè)的變量的范圍,使用..<符號即可境肾。

注意Swift使用花括號剔难,而非縮進形式來表示代碼層次結(jié)構(gòu)

在Swift中也可以使用比較經(jīng)典的while和for循環(huán)。You can learn more about loops in Swift here

條件

這里就是非常經(jīng)典的if語句了奥喻,不做贅述偶宫。

Swift中條件語句針對Optional類型做了專門的優(yōu)化。

函數(shù)

下圖是Swift函數(shù)的定義形式

image

代碼中的注釋

Swift中的注釋形式和C/C++比較像:用//來開始行注釋环鲤,用/* ... */來常見塊注釋纯趋。在代碼中多寫注釋是一個好習慣。

在Swift中使用Python的庫

Swift支持和Python的互操作,這意味著你可以直接在Swift中使用大部分Python庫:調(diào)用函數(shù)或者做變量的類型轉(zhuǎn)換吵冒。這個特性大大增強了Swift的功能纯命。盡管Swift的生態(tài)還非常年輕,但是我們可以直接使用非常成熟的Python庫痹栖,如Numpy亿汞,Pandas還有Matplotlib等。

為了引用Python模塊揪阿,我們只需要將Swift的Python模塊導入疗我,然后使用這個模塊的接口即可:

import Python

// Load numpy from python
let np = Python.import("numpy")

// create array of zeros
var zeros = np.ones([2, 3])
print(zeros)

matplotlib庫也可以直接導入:

image

在Swift中使用Tensorflow創(chuàng)建一個基礎(chǔ)模型

image

Swift4Tensorflow是Swift生態(tài)中一個非常成熟的庫。我們可以用非常類似Keras的方式來創(chuàng)建機器學習和深度學習的模塊南捂。

有意思的是吴裤,Swift4Tensorflow不只是一個簡單的Tensorflow的Swift語言打包,而是根據(jù)Swift本身語言開發(fā)的庫溺健。未來這個庫可能會變成Swift的語言的核心部分麦牺。

<i>What this means is that the amazing set of Engineers from Apple’s Swift team and Google’s Tensorflow team will make sure that you are able to do high-performance machine learning in Swift.</i>

這個庫加入了一些Swift語言的有用特性,如自動微分支持(這讓我想起了PyTorch中的Autogrid)鞭缭。

image

關(guān)于數(shù)據(jù)集

首先讓我們來解釋一下這個section的問題枕面。如果你之前接觸過深度學習領(lǐng)域,你應(yīng)該比較熟悉了缚去。

我們將會建立一個卷積神經(jīng)網(wǎng)絡(luò)(CNN)模型來將MNIST數(shù)據(jù)集中的圖片識別為數(shù)字字符。MNIST數(shù)據(jù)集包括60,000個訓練圖像和10,000個測試圖像琼开。圖像為手寫的數(shù)字字符易结。

image

這個數(shù)據(jù)集是研究計算機視覺的時候一個非常常用的數(shù)據(jù)集,所以我在這里不做細節(jié)性的描述柜候。要了解更多搞动,你可以讀一下這個

配置羨慕

在我們開始創(chuàng)建模塊之前渣刷。我們需要下載數(shù)據(jù)集并進行預(yù)處理鹦肿。為了你的方便我已經(jīng)創(chuàng)建了一個Github倉庫,提供了預(yù)處理代碼以及數(shù)據(jù)辅柴。讓我們下載配置代碼箩溃,下載數(shù)據(jù)集并導入黑色的庫。

%include "EnableIPythonDisplay.swift"
IPythonDisplay.shell.enable_matplotlib("inline")

import Foundation
import Python

let os = Python.import("os")
let plt = Python.import("matplotlib.pyplot")

os.system("git clone https://github.com/mohdsanadzakirizvi/swift-datascience.git")
os.chdir("/content/swift-datascience")

運行上面的代碼碌嘀,數(shù)據(jù)集就會下載到Colab的環(huán)境中了涣旨。

在本地運行時代碼應(yīng)該需要修改,這個我們后面來討論

不過這個操作太丑陋了股冗,沒有使用Swift的native方法來調(diào)用shell命令霹陡。

載入數(shù)據(jù)

%include "/content/swift-datascience/MNIST.swift"

// Load dataset
let dataset = MNIST(batchSize: 128)

// Get first 5 images
let imgs = dataset.trainingImages.minibatch(at: 0, batchSize: 5).makeNumpyArray()
print(imgs.shape)

查看一下數(shù)據(jù)集

我們嘗試畫出數(shù)據(jù)集中的圖片來看看我們要處理的問題:

# Display first 5 images
for img in imgs{
  plt.imshow(img.reshape(28,28))
  plt.show()
}

畫出來大概是下面的樣子:

image

定義模型結(jié)構(gòu)

現(xiàn)在讓我們來定義我們的模型的結(jié)構(gòu)。這里我使用了LeNet-5架構(gòu),一個非撑朊蓿基礎(chǔ)的CNN模型攒霹,包含兩個卷基層,average pooling還有三個Dense層【~應(yīng)該是全連接層浆洗?】催束。最后一級dense layer的輸出維數(shù)是10,因為我們有10個類別要輸出辅髓,分別代表0-9.

import TensorFlow

let epochCount = 100
let batchSize = 128

// The LeNet-5 model
var classifier = Sequential {
    Conv2D<Float>(filterShape: (5, 5, 1, 6), padding: .same, activation: relu)
    AvgPool2D<Float>(poolSize: (2, 2), strides: (2, 2))
    Conv2D<Float>(filterShape: (5, 5, 6, 16), activation: relu)
    AvgPool2D<Float>(poolSize: (2, 2), strides: (2, 2))
    Flatten<Float>()
    Dense<Float>(inputSize: 400, outputSize: 120, activation: relu)
    Dense<Float>(inputSize: 120, outputSize: 84, activation: relu)
    Dense<Float>(inputSize: 84, outputSize: 10, activation: softmax)
}

你可能已經(jīng)注意到了泣崩,上面的代碼和你在Keras(或者PyTorch,TensorFlow)中寫的Python代碼非常類似

<i>The simplicity of writing code is one of the biggest points of Swift.</i>

Swift4Tensorflow支持很多現(xiàn)成的多層模型洛口。更多閱讀參考:https://www.tensorflow.org/swift/api_docs/Structs

選擇梯度下降作為Optimizer

類似的矫付,這里我們也需要選擇Optimizer來優(yōu)化我們的模型。我們這里選擇使用隨機梯度下降算法(stochastic gradient descent, SGD)第焰。

let optimizer = SGD(for: classifier, learningRate: 0.1)

Swift4Tensorflow還支持很多Optimizer:

  • AMSGrad
  • AdaDelta
  • AdaGrad
  • AdaMax
  • Adam
  • Parameter
  • RMSProp
  • SGD

模型訓練

現(xiàn)在萬事俱備了买优,讓我們開始訓練模型吧。

print("Beginning training...")

struct Statistics {
    var correctGuessCount: Int = 0
    var totalGuessCount: Int = 0
    var totalLoss: Float = 0
}

// Store accuracy results during training
var trainAccuracyResults: [Float] = []
var testAccuracyResults: [Float] = []

// The training loop.
for epoch in 1...epochCount {
    var trainStats = Statistics()
    var testStats = Statistics()

    // Set context to training 
    Context.local.learningPhase = .training

    for i in 0 ..< dataset.trainingSize / batchSize {
        // Get mini-batches of x and y
        let x = dataset.trainingImages.minibatch(at: i, batchSize: batchSize)
        let y = dataset.trainingLabels.minibatch(at: i, batchSize: batchSize)
        
        // Compute the gradient with respect to the model.
        let ??model = classifier.gradient { classifier -> Tensor<Float> in
            let ? = classifier(x)
            let correctPredictions = ?.argmax(squeezingAxis: 1) .== y
            
            trainStats.correctGuessCount += Int(Tensor<Int32>(correctPredictions).sum().scalarized())
            trainStats.totalGuessCount += batchSize
            
            let loss = softmaxCrossEntropy(logits: ?, labels: y)
            trainStats.totalLoss += loss.scalarized()
            
            return loss
        }
        
        // Update the model's differentiable variables along the gradient vector.
        optimizer.update(&classifier, along: ??model)
    }

    // Set context to inference
    Context.local.learningPhase = .inference

    for i in 0 ..< dataset.testSize / batchSize {
        let x = dataset.testImages.minibatch(at: i, batchSize: batchSize)
        let y = dataset.testLabels.minibatch(at: i, batchSize: batchSize)

        // Compute loss on test set
        let ? = classifier(x)
        let correctPredictions = ?.argmax(squeezingAxis: 1) .== y

        testStats.correctGuessCount += Int(Tensor<Int32>(correctPredictions).sum().scalarized())
        testStats.totalGuessCount += batchSize

        let loss = softmaxCrossEntropy(logits: ?, labels: y)

        testStats.totalLoss += loss.scalarized()
    }

    let trainAccuracy = Float(trainStats.correctGuessCount) / Float(trainStats.totalGuessCount)
    let testAccuracy = Float(testStats.correctGuessCount) / Float(testStats.totalGuessCount)

    // Save train and test accuracy
    trainAccuracyResults.append(trainAccuracy)
    testAccuracyResults.append(testAccuracy)

    print("""
          [Epoch \(epoch)] \
          Training Loss: \(trainStats.totalLoss), \
          Training Accuracy: \(trainStats.correctGuessCount)/\(trainStats.totalGuessCount) \
          (\(trainAccuracy)), \
          Test Loss: \(testStats.totalLoss), \
          Test Accuracy: \(testStats.correctGuessCount)/\(testStats.totalGuessCount) \
          (\(testAccuracy))
          """)
}

上面的代碼中用了一些fancy的數(shù)學符號挺举,但是由于這些符號輸入并不方便杀赢,因此實際編程中我們不會這么做。

上面的代碼流程中我們將數(shù)據(jù)集的樣本傳遞給模型湘纵,幫助其改善預(yù)測精度脂崔。訓練步驟如下:

  1. 訓練重復(fù)若干次,每次我們遍歷整個訓練集梧喷。
  2. 在每次訓練迭代中砌左,我們逐個傳入features(x)和labels(y),這對下一步非常重要铺敌。
  3. 使用樣本的features汇歹,使用模型做出預(yù)測,并與labels提供的真值進行比對偿凭,進而計算出模型的損失函數(shù)和下降梯度方向产弹。
  4. 這是梯度下降算法發(fā)揮了作用,我們沿著梯度方向更新模型的變量弯囊。
  5. 追蹤訓練過程中的一些統(tǒng)計數(shù)據(jù)來方便我們后續(xù)做可視化痰哨。
  6. 在第一步提到的重復(fù)訓練中,每次重復(fù)2至5步匾嘱。

epochCount變量為重復(fù)遍歷數(shù)據(jù)集的次數(shù)作谭。你可以修改其值嘗試一下。

需要多少次遍歷來取得90%以上的正確率呢奄毡?我可以在12次訓練下在訓練集和測試集上獲得97%以上的正確率折欠。

<img src="https://imgs.codewoody.com/uploads/big/5b367d407d32802ecce0bcd33b3e9f9a.png" alt="" style="border: none;"/>

可視化輸出訓練過程

用下面的方法我么可以可視化輸出訓練過程中的誤差演變過程:

plt.figure(figsize: [12, 8])

let accuracyAxes = plt.subplot(2, 1, 1)
accuracyAxes.set_ylabel("Train Accuracy")
accuracyAxes.plot(trainAccuracyResults, color: "blue")

let lossAxes = plt.subplot(2, 1, 2)
lossAxes.set_ylabel("Test Accuracy")
lossAxes.set_xlabel("Epoch")
lossAxes.plot(testAccuracyResults, color: "yellow")

plt.show()

得到的結(jié)果如下圖所示:

image

Swift數(shù)據(jù)科學應(yīng)用的未來

有產(chǎn)業(yè)專家對Swift做出了很高的評價,認為其有潛力成為數(shù)據(jù)科學的主流語言,同時也能成為機器學習類應(yīng)用開發(fā)的主要工具锐秦。

目前咪奖,很多fancy的數(shù)據(jù)科學相關(guān)的Swift庫還在開發(fā)中,其背后有強大的業(yè)界支持酱床。我非逞蛘裕看好Swift生態(tài)的未來--甚至會比現(xiàn)在的Python更加強大。

下面是一些你可以進一步研究的Swift庫:

本文涉及的所有代碼托管在Github上扇谣。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末昧捷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子罐寨,更是在濱河造成了極大的恐慌靡挥,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸯绿,死亡現(xiàn)場離奇詭異跋破,居然都是意外死亡,警方通過查閱死者的電腦和手機瓶蝴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門毒返,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人舷手,你說我怎么就攤上這事拧簸。” “怎么了男窟?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵盆赤,是天一觀的道長。 經(jīng)常有香客問我蝎宇,道長,這世上最難降的妖魔是什么祷安? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任姥芥,我火速辦了婚禮,結(jié)果婚禮上汇鞭,老公的妹妹穿的比我還像新娘凉唐。我一直安慰自己,他們只是感情好霍骄,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布台囱。 她就那樣靜靜地躺著,像睡著了一般读整。 火紅的嫁衣襯著肌膚如雪簿训。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音强品,去河邊找鬼膘侮。 笑死,一個胖子當著我的面吹牛的榛,可吹牛的內(nèi)容都是我干的琼了。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼夫晌,長吁一口氣:“原來是場噩夢啊……” “哼雕薪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起晓淀,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤所袁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后要糊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纲熏,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年锄俄,在試婚紗的時候發(fā)現(xiàn)自己被綠了局劲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡奶赠,死狀恐怖鱼填,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情毅戈,我是刑警寧澤苹丸,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站苇经,受9級特大地震影響赘理,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扇单,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一商模、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜘澜,春花似錦施流、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至装诡,卻和暖如春银受,著一層夾襖步出監(jiān)牢的瞬間践盼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工蚓土, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宏侍,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓蜀漆,卻偏偏與公主長得像谅河,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子确丢,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一绷耍、Python簡介和環(huán)境搭建以及pip的安裝 4課時實驗課主要內(nèi)容 【Python簡介】: Python 是一個...
    _小老虎_閱讀 5,746評論 0 10
  • 自入秋以來,身體不斷的報警鲜侥,狀況百出褂始,讓我意識到健康狀況已經(jīng)不容小覷。 每日在接送完孩子之后描函,我刻意讓自己多繞一些...
    elaine辛辛閱讀 284評論 0 0
  • 2018年8月5日 星期日 晴 《跨界歌王第三季》節(jié)目共13期崎苗。該節(jié)目旨在突破固有的娛樂邊界,匯集了活躍在影...
    瀟湘月明閱讀 565評論 0 1
  • 我是南京博贊思維導圖管理師認證班T7班郭倩扦 我相信在自己能力范圍內(nèi)盡全力去做舀寓,必有驚喜胆数! 指導老師:汪志鵬 童櫟...
    T7班郭倩扦閱讀 328評論 0 0
  • 烏龜是一種憨態(tài)可掬的動物,很討人喜歡互墓。 它四肢短小灵迫,行動笨拙愕撰。玲瓏的小腦袋上嵌著一對閃閃發(fā)光的小眼睛躬充。身上有堅硬的...
    晨曦班王岳閱讀 354評論 0 0