package p2p

10年積累的成都做網(wǎng)站、成都網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有石嘴山免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
import (
"context"
"errors"
"time"
net "gx/ipfs/QmPjvxTpVH8qJyQDnxnsxF9kv9jezKD1kozz1hs3fCGsNh/go-libp2p-net"
manet "gx/ipfs/QmV6FjemM1K8oXjrvuq3wuVWWoU2TLDPmNnKrxHzY3v6Ai/go-multiaddr-net"
ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr"
pro "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol"
pstore "gx/ipfs/QmZR2XWVVBCtbgBWnQhWk2xcQfaR3W8faQPriAiaaj7rsr/go-libp2p-peerstore"
p2phost "gx/ipfs/Qmb8T6YBBsjYsVGfrihQLfCJveczZnneSBqBKkYEBWDjge/go-libp2p-host"
peer "gx/ipfs/QmdVrMn1LhB4ybb8hMVaMLXnA8XRSewMnK6YqXKXoTcRvN/go-libp2p-peer"
)
//P2P結(jié)構(gòu)保存當(dāng)前正在運(yùn)行的流/監(jiān)聽(tīng)器的信息
// P2P structure holds information on currently running streams/listeners
type P2P struct {
//監(jiān)聽(tīng)器
Listeners ListenerRegistry
//數(shù)據(jù)流
Streams StreamRegistry
//節(jié)點(diǎn)ID
identity peer.ID
//節(jié)點(diǎn)地址
peerHost p2phost.Host
//一個(gè)線程安全的對(duì)等節(jié)點(diǎn)存儲(chǔ)
peerstore pstore.Peerstore
}
//創(chuàng)建一個(gè)新的p2p結(jié)構(gòu)
// NewP2P creates new P2P struct
//這個(gè)新的p2p結(jié)構(gòu)不包含p2p結(jié)構(gòu)中的監(jiān)聽(tīng)器和數(shù)據(jù)流
func NewP2P(identity peer.ID, peerHost p2phost.Host, peerstore pstore.Peerstore) *P2P {
return P2P{
identity: identity,
peerHost: peerHost,
peerstore: peerstore,
}
}
//新建一個(gè)數(shù)據(jù)流 工具方法 構(gòu)建一個(gè)有節(jié)點(diǎn)id,內(nèi)容和協(xié)議的流
func (p2p P2P) newStreamTo(ctx2 context.Context, p peer.ID, protocol string) (net.Stream, error) {
//30s 后會(huì)自動(dòng)timeout
ctx, cancel := context.WithTimeout(ctx2, time.Second 30) //TODO: configurable?
defer cancel()
err := p2p.peerHost.Connect(ctx, pstore.PeerInfo{ID: p})
if err != nil {
return nil, err
}
return p2p.peerHost.NewStream(ctx2, p, pro.ID(protocol))
}
//對(duì)話為遠(yuǎn)程監(jiān)聽(tīng)器創(chuàng)建新的P2P流
//創(chuàng)建一個(gè)新的p2p流實(shí)現(xiàn)對(duì)對(duì)話的監(jiān)聽(tīng)
// Dial creates new P2P stream to a remote listener
//Multiaddr是一種跨協(xié)議、跨平臺(tái)的表示格式的互聯(lián)網(wǎng)地址。它強(qiáng)調(diào)明確性和自我描述。
//對(duì)內(nèi)接收
func (p2p P2P) Dial(ctx context.Context, addr ma.Multiaddr, peer peer.ID, proto string, bindAddr ma.Multiaddr) ( ListenerInfo, error) {
//獲取一些節(jié)點(diǎn)信息 network, host, nil
lnet, _, err := manet.DialArgs(bindAddr)
if err != nil {
return nil, err
}
//監(jiān)聽(tīng)信息
listenerInfo := ListenerInfo{
//節(jié)點(diǎn)身份
Identity: p2p.identity,
////應(yīng)用程序協(xié)議標(biāo)識(shí)符。
Protocol: proto,
}
//調(diào)用newStreamTo 通過(guò)ctx(內(nèi)容) peer(節(jié)點(diǎn)id) proto(協(xié)議標(biāo)識(shí)符) 參數(shù)獲取一個(gè)新的數(shù)據(jù)流
remote, err := p2p.newStreamTo(ctx, peer, proto)
if err != nil {
return nil, err
}
//network協(xié)議標(biāo)識(shí)
switch lnet {
//network為"tcp", "tcp4", "tcp6"
case "tcp", "tcp4", "tcp6":
//從監(jiān)聽(tīng)器獲取新的信息 nla.Listener, nil
listener, err := manet.Listen(bindAddr)
if err != nil {
if err2 := remote.Reset(); err2 != nil {
return nil, err2
}
return nil, err
}
//將獲取的新信息保存到listenerInfo
listenerInfo.Address = listener.Multiaddr()
listenerInfo.Closer = listener
listenerInfo.Running = true
//開(kāi)啟接受
go p2p.doAccept(listenerInfo, remote, listener)
default:
return nil, errors.New("unsupported protocol: " + lnet)
}
return listenerInfo, nil
}
//
func (p2p *P2P) doAccept(listenerInfo *ListenerInfo, remote net.Stream, listener manet.Listener) {
//關(guān)閉偵聽(tīng)器并刪除流處理程序
defer listener.Close()
//Returns a Multiaddr friendly Conn
//一個(gè)有好的 Multiaddr 連接
local, err := listener.Accept()
if err != nil {
return
}
stream := StreamInfo{
//連接協(xié)議
Protocol: listenerInfo.Protocol,
//定位節(jié)點(diǎn)
LocalPeer: listenerInfo.Identity,
//定位節(jié)點(diǎn)地址
LocalAddr: listenerInfo.Address,
//遠(yuǎn)程節(jié)點(diǎn)
RemotePeer: remote.Conn().RemotePeer(),
//遠(yuǎn)程節(jié)點(diǎn)地址
RemoteAddr: remote.Conn().RemoteMultiaddr(),
//定位
Local: local,
//遠(yuǎn)程
Remote: remote,
//注冊(cè)碼
Registry: p2p.Streams,
}
//注冊(cè)連接信息
p2p.Streams.Register(stream)
//開(kāi)啟節(jié)點(diǎn)廣播
stream.startStreaming()
}
//偵聽(tīng)器將流處理程序包裝到偵聽(tīng)器中
// Listener wraps stream handler into a listener
type Listener interface {
Accept() (net.Stream, error)
Close() error
}
//P2PListener保存關(guān)于偵聽(tīng)器的信息
// P2PListener holds information on a listener
type P2PListener struct {
peerHost p2phost.Host
conCh chan net.Stream
proto pro.ID
ctx context.Context
cancel func()
}
//等待偵聽(tīng)器的連接
// Accept waits for a connection from the listener
func (il *P2PListener) Accept() (net.Stream, error) {
select {
case c := -il.conCh:
return c, nil
case -il.ctx.Done():
return nil, il.ctx.Err()
}
}
//關(guān)閉偵聽(tīng)器并刪除流處理程序
// Close closes the listener and removes stream handler
func (il *P2PListener) Close() error {
il.cancel()
il.peerHost.RemoveStreamHandler(il.proto)
return nil
}
// Listen創(chuàng)建新的P2PListener
// Listen creates new P2PListener
func (p2p P2P) registerStreamHandler(ctx2 context.Context, protocol string) ( P2PListener, error) {
ctx, cancel := context.WithCancel(ctx2)
list := P2PListener{
peerHost: p2p.peerHost,
proto: pro.ID(protocol),
conCh: make(chan net.Stream),
ctx: ctx,
cancel: cancel,
}
p2p.peerHost.SetStreamHandler(list.proto, func(s net.Stream) {
select {
case list.conCh - s:
case -ctx.Done():
s.Reset()
}
})
return list, nil
}
// NewListener創(chuàng)建新的p2p偵聽(tīng)器
// NewListener creates new p2p listener
//對(duì)外廣播
func (p2p P2P) NewListener(ctx context.Context, proto string, addr ma.Multiaddr) ( ListenerInfo, error) {
//調(diào)用registerStreamHandler 構(gòu)造一個(gè)新的listener
listener, err := p2p.registerStreamHandler(ctx, proto)
if err != nil {
return nil, err
}
//構(gòu)造新的listenerInfo
listenerInfo := ListenerInfo{
Identity: p2p.identity,
Protocol: proto,
Address: addr,
Closer: listener,
Running: true,
Registry: p2p.Listeners,
}
go p2p.acceptStreams(listenerInfo, listener)
//注冊(cè)連接信息
p2p.Listeners.Register(listenerInfo)
return listenerInfo, nil
}
//接受流
func (p2p *P2P) acceptStreams(listenerInfo *ListenerInfo, listener Listener) {
for listenerInfo.Running {
//一個(gè)有好的 遠(yuǎn)程 連接
remote, err := listener.Accept()
if err != nil {
listener.Close()
break
}
}
//取消注冊(cè)表中的p2p偵聽(tīng)器
p2p.Listeners.Deregister(listenerInfo.Protocol)
}
// CheckProtoExists檢查是否注冊(cè)了協(xié)議處理程序
// mux處理程序
// CheckProtoExists checks whether a protocol handler is registered to
// mux handler
func (p2p *P2P) CheckProtoExists(proto string) bool {
protos := p2p.peerHost.Mux().Protocols()
for _, p := range protos {
if p != proto {
continue
}
return true
}
return false
}
1.找淺顯易懂,例程比較好的教程,從頭到尾看下去。不要看很多本,專注于一本。把里面的例程都手打一遍,搞懂為什么。
2.去找實(shí)際項(xiàng)目練手。最好是要有真實(shí)的項(xiàng)目做。可以找?guī)讉€(gè)同學(xué)一起做個(gè)網(wǎng)站之類。注意,真實(shí)項(xiàng)目不一定非要是商業(yè)項(xiàng)目。
3.最好能找到一個(gè)已經(jīng)會(huì)python的人。問(wèn)他一點(diǎn)學(xué)習(xí)規(guī)劃的建議,然后在遇到卡殼的地方找他指點(diǎn)。這樣會(huì)事半功倍。
4.另外,除了學(xué)習(xí)編程語(yǔ)言,也兼顧補(bǔ)一點(diǎn)計(jì)算機(jī)基礎(chǔ),和英語(yǔ)。
5.不但要學(xué)寫(xiě)代碼,還要學(xué)會(huì)看代碼,更要會(huì)調(diào)試代碼。讀懂你自己程序的報(bào)錯(cuò)信息。再去找些github上的程序,讀懂別人的代碼。
6.學(xué)會(huì)查文檔,用好搜索引擎和開(kāi)發(fā)者社區(qū)。
想學(xué)Python的童鞋可以加企鵝裙前三位是227,中間是435,后三位是450分享軟件視頻資料
學(xué)Python和學(xué)其他的語(yǔ)言其實(shí)是相同的,我給新同事講課的時(shí)候就說(shuō)學(xué)編程和練武功其實(shí)是很相似,入門(mén)大致這樣幾步:
找本靠譜的書(shū),
找個(gè)靠譜的師傅,
找一個(gè)地方開(kāi)始練習(xí)。
學(xué)語(yǔ)言也是的:選一本通俗易懂的書(shū),找一個(gè)好的視頻資料,然后自己裝一個(gè)IDE工具開(kāi)始邊學(xué)變寫(xiě)。下面我具體來(lái)講講:
1.找一本靠譜的書(shū),難度一定要是入門(mén)級(jí)別,千萬(wàn)不能太復(fù)雜,不要一下子陷進(jìn)去,會(huì)打亂節(jié)奏,學(xué)東西要循序漸進(jìn),不能一口吃個(gè)胖子.打個(gè)比方,學(xué)過(guò)java的同學(xué)都聽(tīng)過(guò)大名鼎鼎的thinking in java,這邊書(shū)很厚很全,若一上來(lái)就學(xué),肯定會(huì)吃力,時(shí)間長(zhǎng)了就會(huì)失去興趣,因此對(duì)初學(xué)者來(lái)說(shuō),一定要找一個(gè)通熟易懂的,簡(jiǎn)單的書(shū)。入門(mén)的書(shū)非常關(guān)鍵。
入門(mén)的書(shū)很多,但是我個(gè)人強(qiáng)烈推薦"A Byte of Python",這本書(shū)我讀了2遍,作者寫(xiě)的思路非常清晰,對(duì)每一個(gè)知識(shí)點(diǎn)講解的很到位,不多不少,剛剛好,對(duì)初學(xué)者來(lái)說(shuō),力道剛剛好。而且是全英文,對(duì)提高自己的英語(yǔ)水平,很有幫助.
網(wǎng)上有人會(huì)推薦"笨辦法學(xué)Python",我個(gè)人覺(jué)得這本書(shū)沒(méi)有"A Byte of Python"好 .一般有一些編程基本,我建議直接看"A Byte of Python".這本書(shū)的銷量已經(jīng)破百萬(wàn)了,而且在豆瓣上點(diǎn)評(píng)有8.8,可謂是入門(mén)級(jí)的神書(shū).電子版大家可以在CSDN 搜一下就有,都是高清的.
2.多編寫(xiě)程序,這似乎是廢話,但是確實(shí)是一句實(shí)話。學(xué)編程一定要親身去編寫(xiě),沒(méi)有什么捷徑.一開(kāi)始哪怕你把書(shū)里面的例子一字不落敲一遍,也好過(guò)你只是去看書(shū),而不動(dòng)手。
而且學(xué)python 最好是堅(jiān)持編,每天抽小半個(gè)小時(shí),學(xué)一些知識(shí)點(diǎn),不斷的堅(jiān)持.大概快的話幾個(gè)星期基本就能入門(mén)了。
以上就是我對(duì)python 入門(mén)的感悟,希望對(duì)初學(xué)者能有一點(diǎn)幫助,能幫到一些人少走一點(diǎn)彎路.也就不枉我大半夜在這里碼字了~~
最后說(shuō)一下,我堅(jiān)持原創(chuàng),若我寫(xiě)的對(duì)大家有幫助,麻煩大家支持一下,也是對(duì)我的一點(diǎn)鼓勵(lì)和動(dòng)力。
當(dāng)然,如果你是0基礎(chǔ),周?chē)矝](méi)有大神帶領(lǐng),自己也學(xué)不進(jìn)去,我勸你還是放棄吧,或者就找個(gè)培訓(xùn)機(jī)構(gòu)花點(diǎn)錢(qián)學(xué)習(xí)
謝謝
繼續(xù)進(jìn)入下一個(gè)初始化
n.netService, err = nebnet.NewNebService(n)
if err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to setup net service.")
}
netservice有兩個(gè)成員
type NebServicestruct {
node? ? ? *Node
dispatcher *Dispatcher
}
跳出stup()函數(shù)
先進(jìn)入start()函數(shù)看一看
if err := n.netService.Start(); err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to start net service.")
}
進(jìn)入netservice.start()
func (ns *NebService) Start() error {
logging.CLog().Info("Starting NebService...")
// start dispatcher.
ns.dispatcher.Start()
// start node.
if err := ns.node.Start(); err != nil {
ns.dispatcher.Stop()
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Error("Failed to start NebService.")
return err
}
logging.CLog().Info("Started NebService.")
return nil
}
可以看到第一個(gè)start()的函數(shù)是dispatcher.start()
進(jìn)入dispatch.start()
func (dp *Dispatcher) Start() {
logging.CLog().Info("Starting NebService Dispatcher...")
go dp.loop()
}
然后就出現(xiàn)一個(gè)新的線程、goruntime
go dp.loop()
進(jìn)入該線程,看它干了些什么
timerChan := time.NewTicker(time.Second).C
for {
select {
case -timerChan:
metricsDispatcherCached.Update(int64(len(dp.receivedMessageCh)))
case -dp.quitCh:
logging.CLog().Info("Stoped NebService Dispatcher.")
return
case msg := -dp.receivedMessageCh:
msgType := msg.MessageType()
v, _ := dp.subscribersMap.Load(msgType)
if v == nil {
continue
? }
m, _ := v.(*sync.Map)
m.Range(func(key, valueinterface{}) bool {
select {
case key.(*Subscriber).msgChan - msg:
default:
logging.VLog().WithFields(logrus.Fields{
"msgType": msgType,
}).Warn("timeout to dispatch message.")
}
return true
? })
}
}
一個(gè)有點(diǎn)長(zhǎng)的循環(huán)
metricsDispatcherCached.Update(int64(len(dp.receivedMessageCh)))一秒鐘刷新一次緩沖區(qū)
case msg := -dp.receivedMessageCh:
msgType := msg.MessageType()如果能取出dp.receivedMessageCh
msgType := msg.MessageType()首先判斷取出的信息類型
v, _ := dp.subscribersMap.Load(msgType)
if v == nil {
continue
}
根據(jù)類型取出相應(yīng)的map
如果取不出,那么使用continue結(jié)束這個(gè)case
m, _ := v.(*sync.Map)
斷言
m.Range(func(key, valueinterface{}) bool {
select {
case key.(*Subscriber).msgChan - msg:
default:
logging.VLog().WithFields(logrus.Fields{
"msgType": msgType,
}).Warn("timeout to dispa+tch message.")
}
return true
})
將msg推入其他管道里面去。其他goruntime會(huì)循環(huán)等待該
任何一門(mén)計(jì)算機(jī)語(yǔ)言,都能在特定某個(gè)領(lǐng)域的應(yīng)用中,實(shí)現(xiàn)區(qū)塊鏈技術(shù);
具體使用哪一門(mén)語(yǔ)言,完全看我們相應(yīng)領(lǐng)域行業(yè)企業(yè)項(xiàng)目的技術(shù)要求,以及更關(guān)鍵的:跟已有信息系統(tǒng)的有效對(duì)接聯(lián)通。
區(qū)塊鏈具有自下而上生成記錄,生成兩方或多方合同類記錄,加入第三方確認(rèn)機(jī)制,分布存儲(chǔ),……等特點(diǎn);
從而讓它相比集中式的存儲(chǔ)運(yùn)算而言,變得更為可信。
常見(jiàn)的總統(tǒng)投票,就非常適合以區(qū)塊鏈技術(shù)重新架構(gòu);采用區(qū)塊鏈技術(shù)的投票系統(tǒng),能夠避免哪一家技術(shù)公司、某一個(gè)關(guān)鍵技術(shù)人員,操縱選票統(tǒng)計(jì)結(jié)果的可能。
像我們的法院證據(jù),也特別適合采用區(qū)塊鏈技術(shù)重新架構(gòu)開(kāi)發(fā)。
其實(shí)像當(dāng)前我們各類互聯(lián)網(wǎng)時(shí)代的“版權(quán)系統(tǒng)”,它們中一些就是采用區(qū)塊鏈技術(shù)架構(gòu)而來(lái),只不過(guò),目前我們的新聞出版局、專利局(或者更廣義地被稱作“專家評(píng)委”),都尚未接入這些由互聯(lián)網(wǎng)公司創(chuàng)新而來(lái)的版權(quán)平臺(tái)。
我們耳熟能詳 的“法大大”(雖然名字不甚好聽(tīng)、甚至乍一聽(tīng)來(lái)有些讓人“摸不著頭腦”),它也其實(shí)正準(zhǔn)備采用最新的區(qū)塊鏈技術(shù)重新架構(gòu);采用區(qū)塊鏈技術(shù)的合同平臺(tái),因?yàn)樽兊酶涌尚牛膊拍芨阌诨ヂ?lián)網(wǎng)時(shí)代人們簽訂各類商務(wù)合同。
還有像我們的“征信系統(tǒng)”,也非常適合以區(qū)塊鏈技術(shù)加以改造。能夠讓它更有說(shuō)服力,而不致于出現(xiàn)一家單位、乃至隨意某個(gè)關(guān)鍵技術(shù)人員,能隨意往其中添加“征信污點(diǎn)數(shù)據(jù)”的情況。
還有像我們的P2P貸款,如果能夠以區(qū)塊鏈技術(shù)重新架構(gòu)的話,也能夠變得更加可信,而不致于出現(xiàn)違約、卷款跑路這樣的失信情況。
相信在IT領(lǐng)域發(fā)展的同學(xué)對(duì)Java很熟悉。Java編程語(yǔ)言排行中一直處于領(lǐng)先地位,這可以直接體現(xiàn)Java的重要。因此很多同學(xué)準(zhǔn)備參加Python培訓(xùn)機(jī)構(gòu)系統(tǒng)學(xué)習(xí)。那么,Python培訓(xùn)機(jī)構(gòu)哪家比較好?下面我們介紹一下。
隨著Java的普及,越來(lái)越多的人了解Java,企業(yè)也會(huì)對(duì)求職者提出更高的要求,他們想招聘一些能馬上開(kāi)始工作的人,所以往往會(huì)招聘一些有項(xiàng)目開(kāi)發(fā)經(jīng)驗(yàn)的人。這就是為什么那么多計(jì)算機(jī)專業(yè)的大學(xué)生找不到工作,所以越來(lái)越多的大學(xué)生會(huì)選擇在畢業(yè)前后參加一些專業(yè)的Python培訓(xùn)課程,以增加他們的實(shí)踐經(jīng)驗(yàn)。只有增強(qiáng)自己的力量,才能立于不敗之地。
Python培訓(xùn)機(jī)構(gòu)哪家比較好?判斷Python培訓(xùn)機(jī)構(gòu)好與壞主要看以下幾個(gè)方面
1.看教學(xué)課程內(nèi)容
學(xué)習(xí)Java技術(shù),最主要是與時(shí)俱進(jìn),掌握的技術(shù)點(diǎn)能夠滿足時(shí)下企業(yè)的用人需求。而想要了解一家培訓(xùn)機(jī)構(gòu)所提供的課程是否新穎,也可以去機(jī)構(gòu)的官網(wǎng)上看看,了解自己想學(xué)習(xí)的學(xué)科的課程大綱。看看學(xué)習(xí)路線圖是如何安排的,有沒(méi)有從零到一的系統(tǒng)搭建,是不是有強(qiáng)化實(shí)訓(xùn)、實(shí)操的比重,有盡量多的項(xiàng)目實(shí)戰(zhàn)。因?yàn)槠髽I(yè)對(duì)Java從業(yè)者的技術(shù)能力和動(dòng)手實(shí)戰(zhàn)能力要求較高。
2.看師資力量
因?yàn)镴ava開(kāi)發(fā)技術(shù)知識(shí)的專業(yè)性很強(qiáng),如果盲目去學(xué)很容易走進(jìn)誤區(qū)。相反,有講師帶領(lǐng),站在巨人的肩膀上,往往事半功倍。畢竟現(xiàn)在這個(gè)時(shí)代只要多跟別人交流才能獲得更多更有價(jià)值的信息,初學(xué)者千萬(wàn)不能閉門(mén)造車(chē)。
3.看口碑
行業(yè)內(nèi)口碑比較好,學(xué)生對(duì)培訓(xùn)機(jī)構(gòu)比較認(rèn)可,這種機(jī)構(gòu)把精力放在了學(xué)生身上的機(jī)構(gòu),才是做教育的應(yīng)有態(tài)度。
4.看就業(yè)情況
以學(xué)生就業(yè)為目標(biāo)的培訓(xùn)機(jī)構(gòu)現(xiàn)在才是最主要的。要知道就業(yè)也是教學(xué)成果的體現(xiàn),沒(méi)有好的教學(xué)保證是做不到好的就業(yè)的。
5.上門(mén)免費(fèi)試聽(tīng)
試聽(tīng)是為了更好的去感受培訓(xùn)機(jī)構(gòu)的課程內(nèi)容、講課風(fēng)格、班級(jí)氛圍等,同時(shí)也能通過(guò)和班上在讀同學(xué)進(jìn)行交流,更進(jìn)一步去了解這家培訓(xùn)機(jī)構(gòu)各個(gè)方面是否符合自己的需要。
是否非常想學(xué)好 Python,一方面被瑣事糾纏,一直沒(méi)能動(dòng)手,另一方面,擔(dān)心學(xué)習(xí)成本太高,心里默默敲著退堂鼓?
幸運(yùn)的是,Python 是一門(mén)初學(xué)者友好的編程語(yǔ)言,想要完全掌握它,你不必花上太多的時(shí)間和精力。
Python 的設(shè)計(jì)哲學(xué)之一就是簡(jiǎn)單易學(xué),體現(xiàn)在兩個(gè)方面:
語(yǔ)法簡(jiǎn)潔明了:相對(duì) Ruby 和 Perl,它的語(yǔ)法特性不多不少,大多數(shù)都很簡(jiǎn)單直接,不玩兒玄學(xué)。
切入點(diǎn)很多:Python 可以讓你可以做很多事情,科學(xué)計(jì)算和數(shù)據(jù)分析、爬蟲(chóng)、Web 網(wǎng)站、游戲、命令行實(shí)用工具等等等等,總有一個(gè)是你感興趣并且愿意投入時(shí)間的。
廢話不多說(shuō),學(xué)會(huì)一門(mén)語(yǔ)言的捷徑只有一個(gè): Getting Started
? 起步階段
任何一種編程語(yǔ)言都包含兩個(gè)部分:硬知識(shí)和軟知識(shí),起步階段的主要任務(wù)是掌握硬知識(shí)。
硬知識(shí)
“硬知識(shí)”指的是編程語(yǔ)言的語(yǔ)法、算法和數(shù)據(jù)結(jié)構(gòu)、編程范式等,例如:變量和類型、循環(huán)語(yǔ)句、分支、函數(shù)、類。這部分知識(shí)也是具有普適性的,看上去是掌握了一種語(yǔ)法,實(shí)際是建立了一種思維。例如:讓一個(gè) Java 程序員去學(xué)習(xí) Python,他可以很快的將 Java 中的學(xué)到的面向?qū)ο蟮闹R(shí) map 到 Python 中來(lái),因此能夠快速掌握 Python 中面向?qū)ο蟮奶匦浴?/p>
如果你是剛開(kāi)始學(xué)習(xí)編程的新手,一本可靠的語(yǔ)法書(shū)是非常重要的。它看上去可能非常枯燥乏味,但對(duì)于建立穩(wěn)固的編程思維是必不可少。
下面列出了一些適合初學(xué)者入門(mén)的教學(xué)材料:
廖雪峰的 Python 教程 ? ?Python 中文教程的翹楚,專為剛剛步入程序世界的小白打造。 ?
笨方法學(xué) Python ? ?這本書(shū)在講解 Python 的語(yǔ)法成分時(shí),還附帶大量可實(shí)踐的例子,非常適合快速起步。 ?
The Hitchhiker’s Guide to Python! ? ?這本指南著重于 Python 的最佳實(shí)踐,不管你是 Python 專家還是新手,都能獲得極大的幫助。 ?
Python 的哲學(xué):
用一種方法,最好是只有一種方法來(lái)做一件事。
學(xué)習(xí)也是一樣,雖然推薦了多種學(xué)習(xí)資料,但實(shí)際學(xué)習(xí)的時(shí)候,最好只選擇其中的一個(gè),堅(jiān)持看完。
必要的時(shí)候,可能需要閱讀講解數(shù)據(jù)結(jié)構(gòu)和算法的書(shū),這些知識(shí)對(duì)于理解和使用 Python 中的對(duì)象模型有著很大的幫助。
軟知識(shí)
“軟知識(shí)”則是特定語(yǔ)言環(huán)境下的語(yǔ)法技巧、類庫(kù)的使用、IDE的選擇等等。這一部分,即使完全不了解不會(huì)使用,也不會(huì)妨礙你去編程,只不過(guò)寫(xiě)出的程序,看上去顯得“傻”了些。
對(duì)這些知識(shí)的學(xué)習(xí),取決于你嘗試解決的問(wèn)題的領(lǐng)域和深度。對(duì)初學(xué)者而言,起步階段極易走火,或者在選擇 Python 版本時(shí)徘徊不決,一會(huì)兒看 2.7 一會(huì)兒又轉(zhuǎn)到 3.0,或者徜徉在類庫(kù)的大海中無(wú)法自拔,Scrapy,Numpy,Django 什么都要試試,或者參與編輯器圣戰(zhàn)、大括號(hào)縮進(jìn)探究、操作系統(tǒng)辯論賽等無(wú)意義活動(dòng),或者整天跪舔語(yǔ)法糖,老想著怎么一行代碼把所有的事情做完,或者去構(gòu)想圣潔的性能安全通用性健壯性全部滿分的解決方案。
很多“大牛”都會(huì)告誡初學(xué)者,用這個(gè)用那個(gè),少走彎路,這樣反而把初學(xué)者推向了真正的彎路。
還不如告訴初學(xué)者,學(xué)習(xí)本來(lái)就是個(gè)需要你去走彎路出 Bug,只能腳踏實(shí)地,沒(méi)有奇跡只有狗屎的過(guò)程。
選擇一個(gè)方向先走下去,哪怕臟丑差,走不動(dòng)了再看看有沒(méi)有更好的解決途徑。
自己走了彎路,你才知道這么做的好處,才能理解為什么人們可以手寫(xiě)狀態(tài)機(jī)去匹配卻偏要發(fā)明正則表達(dá)式,為什么面向過(guò)程可以解決卻偏要面向?qū)ο螅瑸槭裁次铱梢圆倏v每一根指針卻偏要自動(dòng)管理內(nèi)存,為什么我可以嵌套回調(diào)卻偏要用 Promise...
更重要的是,你會(huì)明白,高層次的解決方法都是對(duì)低層次的封裝,并不是任何情況下都是最有效最合適的。
技術(shù)涌進(jìn)就像波浪一樣,那些陳舊的封存已久的技術(shù),消退了遲早還會(huì)涌回的。就像現(xiàn)在移動(dòng)端應(yīng)用、手游和 HTML5 的火熱,某些方面不正在重演過(guò)去 PC 的那些歷史么?
因此,不要擔(dān)心自己走錯(cuò)路誤了終身,堅(jiān)持并保持進(jìn)步才是正道。
起步階段的核心任務(wù)是掌握硬知識(shí),軟知識(shí)做適當(dāng)了解,有了穩(wěn)固的根,粗壯的枝干,才能長(zhǎng)出濃密的葉子,結(jié)出甜美的果實(shí)。
? 發(fā)展階段
完成了基礎(chǔ)知識(shí)的學(xué)習(xí),必定會(huì)感到一陣空虛,懷疑這些語(yǔ)法知識(shí)是不是真的有用。
沒(méi)錯(cuò),你的懷疑是非常正確的。要讓 Python 發(fā)揮出它的價(jià)值,當(dāng)然不能停留在語(yǔ)法層面。
發(fā)展階段的核心任務(wù),就是“跳出 Python,擁抱世界”。
在你面前會(huì)有多個(gè)分支:科學(xué)計(jì)算和數(shù)據(jù)分析、爬蟲(chóng)、Web 網(wǎng)站、游戲、命令行實(shí)用工具等等等等,這些都不是僅僅知道 Python 語(yǔ)法就能解決的問(wèn)題。
拿爬蟲(chóng)舉例,如果你對(duì)計(jì)算機(jī)網(wǎng)絡(luò),HTTP 協(xié)議,HTML,文本編碼,JSON 一無(wú)所知,你能做好這部分的工作么?而你在起步階段的基礎(chǔ)知識(shí)也同樣重要,如果你連循環(huán)遞歸怎么寫(xiě)都還要查文檔,連 BFS 都不知道怎么實(shí)現(xiàn),這就像工匠做石凳每次起錘都要思考錘子怎么使用一樣,非常低效。
在這個(gè)階段,不可避免要接觸大量類庫(kù),閱讀大量書(shū)籍的。
類庫(kù)方面
「Awesome Python 項(xiàng)目」:vinta/awesome-python · GitHub
這里列出了你在嘗試解決各種實(shí)際問(wèn)題時(shí),Python 社區(qū)已有的工具型類庫(kù),如下圖所示:
請(qǐng)點(diǎn)擊輸入圖片描述
vinta/awesome-python
你可以按照實(shí)際需求,尋找你需要的類庫(kù)。
至于相關(guān)類庫(kù)如何使用,必須掌握的技能便是閱讀文檔。由于開(kāi)源社區(qū)大多數(shù)文檔都是英文寫(xiě)成的,所以,英語(yǔ)不好的同學(xué),需要惡補(bǔ)下。
書(shū)籍方面
這里我只列出一些我覺(jué)得比較有一些幫助的書(shū)籍,詳細(xì)的請(qǐng)看豆瓣的書(shū)評(píng):
科學(xué)和數(shù)據(jù)分析:
?「集體智慧編程」:集體智慧編程 (豆瓣)
?「數(shù)學(xué)之美」:數(shù)學(xué)之美 (豆瓣)
?「統(tǒng)計(jì)學(xué)習(xí)方法」:統(tǒng)計(jì)學(xué)習(xí)方法 (豆瓣)
?「Pattern Recognition And Machine Learning」:Pattern Recognition And Machine Learning (豆瓣)
?「數(shù)據(jù)科學(xué)實(shí)戰(zhàn)」:數(shù)據(jù)科學(xué)實(shí)戰(zhàn) (豆瓣)
?「數(shù)據(jù)檢索導(dǎo)論」:信息檢索導(dǎo)論 (豆瓣)
爬蟲(chóng):
?「HTTP 權(quán)威指南」:HTTP權(quán)威指南 (豆瓣)
Web 網(wǎng)站:
?「HTML CSS 設(shè)計(jì)與構(gòu)建網(wǎng)站」:HTML CSS設(shè)計(jì)與構(gòu)建網(wǎng)站 (豆瓣)
...
列到這里已經(jīng)不需要繼續(xù)了。
聰明的你一定會(huì)發(fā)現(xiàn)上面的大部分書(shū)籍,并不是講 Python 的書(shū),而更多的是專業(yè)知識(shí)。
事實(shí)上,這里所謂“跳出 Python,擁抱世界”,其實(shí)是發(fā)現(xiàn) Python 和專業(yè)知識(shí)相結(jié)合,能夠解決很多實(shí)際問(wèn)題。這個(gè)階段能走到什么程度,更多的取決于自己的專業(yè)知識(shí)。
? 深入階段
這個(gè)階段的你,對(duì) Python 幾乎了如指掌,那么你一定知道 Python 是用 C 語(yǔ)言實(shí)現(xiàn)的。
可是 Python 對(duì)象的“動(dòng)態(tài)特征”是怎么用相對(duì)底層,連自動(dòng)內(nèi)存管理都沒(méi)有的C語(yǔ)言實(shí)現(xiàn)的呢?這時(shí)候就不能停留在表面了,勇敢的拆開(kāi) Python 的黑盒子,深入到語(yǔ)言的內(nèi)部,去看它的歷史,讀它的源碼,才能真正理解它的設(shè)計(jì)思路。
這里推薦一本書(shū):
「Python 源碼剖析」:Python源碼剖析 (豆瓣)
這本書(shū)把 Python 源碼中最核心的部分,給出了詳細(xì)的闡釋,不過(guò)閱讀此書(shū)需要對(duì) C 語(yǔ)言內(nèi)存模型和指針有著很好的理解。
另外,Python 本身是一門(mén)雜糅多種范式的動(dòng)態(tài)語(yǔ)言,也就是說(shuō),相對(duì)于 C 的過(guò)程式、 Haskell 等的函數(shù)式、Java 基于類的面向?qū)ο蠖裕疾粔蚣兇狻Q而言之,編程語(yǔ)言的“道學(xué)”,在 Python 中只能有限的體悟。學(xué)習(xí)某種編程范式時(shí),從那些面向這種范式更加純粹的語(yǔ)言出發(fā),才能有更深刻的理解,也能了解到 Python 語(yǔ)言的根源。
這里推薦一門(mén)公開(kāi)課
「編程范式」:斯坦福大學(xué)公開(kāi)課:編程范式
講師高屋建瓴,從各種編程范式的代表語(yǔ)言出發(fā),給出了每種編程范式最核心的思想。
值得一提的是,這門(mén)課程對(duì)C語(yǔ)言有非常深入的講解,例如C語(yǔ)言的范型和內(nèi)存管理。這些知識(shí),對(duì)閱讀 Python 源碼也有大有幫助。
Python 的許多最佳實(shí)踐都隱藏在那些眾所周知的框架和類庫(kù)中,例如 Django、Tornado 等等。在它們的源代碼中淘金,也是個(gè)不錯(cuò)的選擇。
? ?最后的話
每個(gè)人學(xué)編程的道路都是不一樣的,其實(shí)大都殊途同歸,沒(méi)有迷路的人只有不能堅(jiān)持的人!
希望想學(xué) Python 想學(xué)編程的同學(xué),不要猶豫了,看完這篇文章,
Just Getting Started ?!!!
當(dāng)前標(biāo)題:go語(yǔ)言p2p項(xiàng)目練手,p2p golang
鏈接分享:http://chinadenli.net/article42/dsgdehc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、動(dòng)態(tài)網(wǎng)站、網(wǎng)站設(shè)計(jì)、外貿(mào)建站、網(wǎng)站營(yíng)銷、用戶體驗(yàn)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)