最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python區(qū)塊鏈簡易版交易完善挖礦獎勵示例

 更新時間:2022年05月31日 10:07:16   作者:曉彬_  
這篇文章主要介紹了python區(qū)塊鏈簡易版交易完善挖礦獎勵示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

說明

本文根據(jù)https://github.com/liuchengxu/blockchain-tutorial的內(nèi)容,用python實現(xiàn)的,但根據(jù)個人的理解進行了一些修改,大量引用了原文的內(nèi)容。文章末尾有"本節(jié)完整源碼實現(xiàn)地址"。

引言

在這個系列文章的一開始,我們就提到了,區(qū)塊鏈是一個分布式數(shù)據(jù)庫。不過在之前的文章中,我們選擇性地跳過了“分布式”這個部分,而是將注意力都放到了“數(shù)據(jù)庫”部分。到目前為止,我們幾乎已經(jīng)實現(xiàn)了一個區(qū)塊鏈數(shù)據(jù)庫的所有元素。今天,我們將會分析之前跳過的一些機制。而在下一篇文章中,我們將會開始討論區(qū)塊鏈的分布式特性。

獎勵

上一篇文章中,我們略過的一個小細節(jié)是挖礦獎勵?,F(xiàn)在,我們已經(jīng)可以來完善這個細節(jié)了。

挖礦獎勵,實際上就是一筆 coinbase 交易。當一個挖礦節(jié)點開始挖出一個新塊時,它會將交易從隊列中取出,并在前面附加一筆 coinbase 交易。coinbase 交易只有一個輸出,里面包含了礦工的公鑰哈希。

實現(xiàn)獎勵,非常簡單,更新 send 即可:

def add_block(self, transactions):
    """
    add a block to block_chain
    """
    last_block = self.get_last_block()
    prev_hash = last_block.get_header_hash()
    height = last_block.block_header.height + 1
    block_header = BlockHeader('', height, prev_hash)
    # reward to wallets[0]
    wallets = Wallets()
    keys = list(wallets.wallets.keys())
    w = wallets[keys[0]]
    coin_base_tx = self.coin_base_tx(w.address)
    transactions.insert(0, coin_base_tx)
    block = Block(block_header, transactions)
    block.mine(self)
    block.set_header_hash()
    self.db.create(block.block_header.hash, block.serialize())
    last_hash = block.block_header.hash
    self.set_last_hash(last_hash)
    utxo = UTXOSet()
    utxo.update(block)

獎勵給當前錢包的第一個地址。

UTXO 集

在 Part 3: 持久化和命令行接口 中,我們研究了 Bitcoin Core 是如何在一個數(shù)據(jù)庫中存儲塊的,并且了解到區(qū)塊被存儲在 blocks 數(shù)據(jù)庫,交易輸出被存儲在 chainstate 數(shù)據(jù)庫。會回顧一下 chainstate 的機構(gòu):

c + 32 字節(jié)的交易哈希 -> 該筆交易的未花費交易輸出記錄

B + 32 字節(jié)的塊哈希 -> 未花費交易輸出的塊哈希

在之前那篇文章中,雖然我們已經(jīng)實現(xiàn)了交易,但是并沒有使用 chainstate 來存儲交易的輸出。所以,接下來我們繼續(xù)完成這部分。

chainstate 不存儲交易。它所存儲的是 UTXO 集,也就是未花費交易輸出的集合。除此以外,它還存儲了“數(shù)據(jù)庫表示的未花費交易輸出的塊哈希”,不過我們會暫時略過塊哈希這一點,因為我們還沒有用到塊高度(但是我們會在接下來的文章中繼續(xù)改進)。

那么,我們?yōu)槭裁葱枰?UTXO 集呢?

來思考一下我們早先實現(xiàn)的 Blockchain._find_unspent_transactions 方法:

def _find_unspent_transactions(self, address):
    """
    Find all unspent transactions
    """
    spent_txos = {}
    unspent_txs = {}
    last_block = self.get_last_block()
    last_height = last_block.block_header.height
    # Reverse
    for height in range(last_height, -1, -1):
        block = self.get_block_by_height(height)
        for tx in block.transactions:
            txid = tx.txid
            # all outputs
            for vout_index, vout in enumerate(tx.vouts):
                txos = spent_txos.get(txid, [])
                # vout_index is spent
                if vout_index in txos:
                    continue
                if vout.can_unlock_output_with(address):
                    old_vouts = unspent_txs.get(tx, [])
                    old_vouts.append(vout)
                    unspent_txs[tx] = old_vouts
            if not tx.is_coinbase():
                for vin in tx.vins:
                    if vin.can_be_unlocked_with(address):
                        txid_vouts = spent_txos.get(txid, [])
                        txid_vouts.append(vin.vout)
                        spent_txos[vin.txid] = txid_vouts
    return unspent_txs

這個函數(shù)找到有未花費輸出的交易。由于交易被保存在區(qū)塊中,所以它會對區(qū)塊鏈里面的每一個區(qū)塊進行迭代,檢查里面的每一筆交易。截止 2017 年 9 月 18 日,在比特幣中已經(jīng)有 485,860 個塊,整個數(shù)據(jù)庫所需磁盤空間超過 140 Gb。這意味著一個人如果想要驗證交易,必須要運行一個全節(jié)點。此外,驗證交易將會需要在許多塊上進行迭代。
整個問題的解決方案是有一個僅有未花費輸出的索引,這就是 UTXO 集要做的事情:這是一個從所有區(qū)塊鏈交易中構(gòu)建(對區(qū)塊進行迭代,但是只須做一次)而來的緩存,然后用它來計算余額和驗證新的交易。截止 2017 年 9 月,UTXO 集大概有 2.7 Gb。

好了,讓我們來想一下實現(xiàn) UTXO 集的話需要作出哪些改變。目前,找到交易用到了以下一些方法:

  • Blockchain._find_unspent_transactions - 找到有未花費輸出交易的主要函數(shù)。也是在這個函數(shù)里面會對所有區(qū)塊進行迭代。
  • Blockchain._find_spendable_outputs - 這個函數(shù)用于當一個新的交易創(chuàng)建的時候。如果找到有所需數(shù)量的輸出。使用 Blockchain._find_unspent_transactions.
  • Blockchain.find_UTXO - 找到一個公鑰哈希的未花費輸出,然后用來獲取余額。使用 Blockchain._find_unspent_transactions.
  • Blockchain.FindTransation - 根據(jù) ID 在區(qū)塊鏈中找到一筆交易。它會在所有塊上進行迭代直到找到它。

可以看到,所有方法都對數(shù)據(jù)庫中的所有塊進行迭代。但是目前我們還沒有改進所有方法,因為 UTXO 集沒法存儲所有交易,只會存儲那些有未花費輸出的交易。因此,它無法用于 Blockchain.FindTransaction。

所以,我們想要以下方法:

  • Blockchain.find_UTXO - 通過對區(qū)塊進行迭代找到所有未花費輸出。
  • UTXOSet.reindex - 使用 UTXO 找到未花費輸出,然后在數(shù)據(jù)庫中進行存儲。這里就是緩存的地方。
  • UTXOSet._find_spendable_outputs - 類似 Blockchain._find_spendable_outputs,但是使用 UTXO 集。
  • UTXOSet.find_UTXO - 類似 Blockchain.find_UTXO,但是使用 UTXO 集。
  • Blockchain.find_transaction 跟之前一樣。

因此,從現(xiàn)在開始,兩個最常用的函數(shù)將會使用 cache!來開始寫代碼吧。

class UTXOSet(Singleton):
    FLAG = 'UTXO'
    def __init__(self, db_url='http://127.0.0.1:5984'):
        self.db = DB(db_url)

這里使用一個FLAG來區(qū)分普通區(qū)塊和UTXO。

def reindex(self, bc):
    key = self.FLAG + "l"
    last_block = bc.get_last_block()
    if key not in self.db:
        utxos = bc.find_UTXO()
        for txid, index_vouts in utxos.items():
            key = self.FLAG + txid
            # outs = []
            for index_vout in index_vouts:
                vout = index_vout[1]
                index = index_vout[0]
                vout_dict = vout.serialize()
                vout_dict.update({"index": index})
                tmp_key = key + "-"+str(index)
                try:
                    self.db.create(tmp_key, vout_dict)
                except ResourceConflict as e:
                    print(e)
        if not last_block:
            return
        self.set_last_height(last_block.block_header.height)
    else:
        utxo_last_height = self.get_last_height()
        last_block_height = last_block.block_header.height
        for i in range(utxo_last_height, last_block_height):
            block = bc.get_block_by_height(i)
            self.update(block)

這個方法首先判斷是否已經(jīng)構(gòu)建過UTXO集,如果沒有構(gòu)建過就從頭開始構(gòu)建UTXO集,如果已經(jīng)構(gòu)建過了,就把當前UTXO的區(qū)塊至最新的區(qū)塊進行更新。
Blockchain.FindUTXO 幾乎跟 Blockchain.FindUnspentTransactions 一模一樣,但是現(xiàn)在它返回了一個 TransactionID -> TransactionOutputs 的 map。

現(xiàn)在,UTXO 集可以用于發(fā)送幣:

def find_spendable_outputs(self, address, amount):
    utxos = self.find_utxo(address)
    accumulated = 0
    spendable_utxos = []
    for ftxo in utxos:
        output = ftxo.txoutput
        accumulated += output.value
        spendable_utxos.append(ftxo)
        if accumulated >= amount:
            break
    return accumulated, spendable_utxos

或者檢查余額:

def find_utxo(self, address):
    query = {
        "selector": {
            "_id": {
                "$regex": "^UTXO"
            },
            "pub_key_hash": address
        }
    }
    docs = self.db.find(query)
    utxos = []
    for doc in docs:
        index = doc.get("index", None)
        if index is None:
            continue
        doc_id = doc.id
        txid_index_str = doc_id.replace(self.FLAG, "")
        _flag_index = txid_index_str.find("-")
        txid = txid_index_str[:_flag_index]
        ftxo = FullTXOutput(txid, TXOutput.deserialize(doc), index)
        utxos.append(ftxo)
    return utxos

有了 UTXO 集,也就意味著我們的數(shù)據(jù)(交易)現(xiàn)在已經(jīng)被分開存儲:實際交易被存儲在區(qū)塊鏈中,未花費輸出被存儲在 UTXO 集中。這樣一來,我們就需要一個良好的同步機制,因為我們想要 UTXO 集時刻處于最新狀態(tài),并且存儲最新交易的輸出。但是我們不想每生成一個新塊,就重新生成索引,因為這正是我們要極力避免的頻繁區(qū)塊鏈掃描。因此,我們需要一個機制來更新 UTXO 集:

def update(self, block):
    for tx in block.transactions:
        txid = tx.txid
        key = self.FLAG + txid
        # add uxto
        for vout_index, vout in enumerate(tx.vouts):
            vout_dict = vout.serialize()
            vout_dict.update({"index": vout_index})
            tmp_key = key + "-" +str(vout_index)
            try:
                self.db.create(tmp_key, vout_dict)
            except ResourceConflict as e:
                print(e)
        # vins delete used utxo
        for vin in tx.vins:
            vin_txid = vin.txid
            key = self.FLAG + vin_txid + "-" +str(vin.vout)
            doc = self.db.get(key)
            if not doc:
                continue
            try:
                self.db.delete(doc)
            except ResourceNotFound as e:
                print(e)
    self.set_last_height(block.block_header.height)

雖然這個方法看起來有點復(fù)雜,但是它所要做的事情非常直觀。當挖出一個新塊時,應(yīng)該更新 UTXO 集。更新意味著移除已花費輸出,并從新挖出來的交易中加入未花費輸出。如果一筆交易的輸出被移除,并且不再包含任何輸出,那么這筆交易也應(yīng)該被移除。相當簡單!

# 創(chuàng)建創(chuàng)世塊
$python3 main.py
<wallet.Wallet object at 0x0000010AED8276A0> <wallet.Wallet object at 0x0000010AED827940>
19RUj6zvbrAXNnEtkuric5pYQJTkZy57nc 17AEyyKbeoEbfMa3jS8Uji6tVG37DrTJN9
Mining a new block
Found nonce == 53ash_hex == 0adfd71d90955ad9219871d8abe03ae83ef9f1f13f9a141ef6ca0ce2d16c93af
('conflict', 'Document update conflict.')
Block(_block_header=BlockHeader(timestamp='1551246051.6814992', hash_merkle_root='1f6cf2e68e8ab0dda1cc1550f85b4df85b83db3cc3af262b26a5a306121725be', prev_block_hash='', hash='ef20a87f2edc8589e813be60d534e736f51c45a3ec94e1918c18bce057afc89d', nonce=None, height=0))
Block(_block_header=BlockHeader(timestamp='1551246052.0582814', hash_merkle_root='3cf2c8514fdaac0cb2b6502f72cf267bcf9966042be28ee48eff61e4695a90f2', prev_block_hash='ef20a87f2edc8589e813be60d534e736f51c45a3ec94e1918c18bce057afc89d', hash='b0bdedf26575722a7efdf94db7dfa60c1c4dfe1483529ff04dd553d6828de718', nonce=53, height=1))
# 轉(zhuǎn)賬
$python3 cli.py send --from 19RUj6zvbrAXNnEtkuric5pYQJTkZy57nc --to 17AEyyKbeoEbfMa3jS8Uji6tVG37DrTJN9 --amount 10
Mining a new block
Found nonce == 20ash_hex == 07e91245d4e66b66279224980b0325c37d2f2e54a75402bdcd8fe55346cb3dcb
send 10 from 19RUj6zvbrAXNnEtkuric5pYQJTkZy57nc to 17AEyyKbeoEbfMa3jS8Uji6tVG37DrTJN9
# 查詢余額
$python3 cli.py balance 19RUj6zvbrAXNnEtkuric5pYQJTkZy57nc
19RUj6zvbrAXNnEtkuric5pYQJTkZy57nc balance is 1980

一切工作正常, 19RUj6zvbrAXNnEtkuric5pYQJTkZy57nc收到了創(chuàng)世塊和轉(zhuǎn)賬的獎勵2000個,轉(zhuǎn)賬了兩次一共使用了20個,剩余1980個。

Merkle 樹

在這篇文章中,我還想要再討論一個優(yōu)化機制。

上如上面所提到的,完整的比特幣數(shù)據(jù)庫(也就是區(qū)塊鏈)需要超過 140 Gb 的磁盤空間。因為比特幣的去中心化特性,網(wǎng)絡(luò)中的每個節(jié)點必須是獨立,自給自足的,也就是每個節(jié)點必須存儲一個區(qū)塊鏈的完整副本。隨著越來越多的人使用比特幣,這條規(guī)則變得越來越難以遵守:因為不太可能每個人都去運行一個全節(jié)點。并且,由于節(jié)點是網(wǎng)絡(luò)中的完全參與者,它們負有相關(guān)責任:節(jié)點必須驗證交易和區(qū)塊。另外,要想與其他節(jié)點交互和下載新塊,也有一定的網(wǎng)絡(luò)流量需求。

在中本聰?shù)?比特幣原始論文 中,對這個問題也有一個解決方案:簡易支付驗證(Simplified Payment Verification, SPV)。SPV 是一個比特幣輕節(jié)點,它不需要下載整個區(qū)塊鏈,也不需要驗證區(qū)塊和交易。相反,它會在區(qū)塊鏈查找交易(為了驗證支付),并且需要連接到一個全節(jié)點來檢索必要的數(shù)據(jù)。這個機制允許在僅運行一個全節(jié)點的情況下有多個輕錢包。

為了實現(xiàn) SPV,需要有一個方式來檢查是否一個區(qū)塊包含了某筆交易,而無須下載整個區(qū)塊。這就是 Merkle 樹所要完成的事情。

比特幣用 Merkle 樹來獲取交易哈希,哈希被保存在區(qū)塊頭中,并會用于工作量證明系統(tǒng)。到目前為止,我們只是將一個塊里面的每筆交易哈希連接了起來,將在上面應(yīng)用了 SHA-256 算法。雖然這是一個用于獲取區(qū)塊交易唯一表示的一個不錯的途徑,但是它沒有利用到 Merkle 樹。

來看一下 Merkle 樹:

每個塊都會有一個 Merkle 樹,它從葉子節(jié)點(樹的底部)開始,一個葉子節(jié)點就是一個交易哈希(比特幣使用雙 SHA256 哈希)。葉子節(jié)點的數(shù)量如果不是雙數(shù),就只取單個數(shù)據(jù)的hash。

從下往上,兩兩成對,連接兩個節(jié)點哈希,將組合哈希作為新的哈希。新的哈希就成為新的樹節(jié)點。重復(fù)該過程,直到僅有一個節(jié)點,也就是樹根。根哈希然后就會當做是整個塊交易的唯一標示,將它保存到區(qū)塊頭,然后用于工作量證明。

Merkle 樹的好處就是一個節(jié)點可以在不下載整個塊的情況下,驗證是否包含某筆交易。并且這些只需要一個交易哈希,一個 Merkle 樹根哈希和一個 Merkle 路徑。

這部分的描述和https://github.com/liuchengxu/blockchain-tutorial/blob/master/content/part-6/transactions-2.md描述有所不同,

因為存在葉子節(jié)點為雙數(shù),但是第二層為單數(shù)的情況,會導(dǎo)致原版代碼出現(xiàn)索引越界的情況。這部分的描述參考http://shouce.jb51.net/blockchain_guide/crypto/merkle_trie.html

實現(xiàn)代碼如下:

class MerkleNode(object):
    def __init__(self, left_node, right_node, data):
        self.left = left_node
        self.right = right_node
        if not self.left and not self.right:
            self.data = sum256_hex(data)
        else:
            data = self.left.data + self.right.data
            self.data = sum256_hex(data)
class MerkleTree(object):
    def __init__(self, datas):
        nodes = []
        for data_item in datas:
            node = MerkleNode(None, None, data_item)
            nodes.append(node)
        for _ in range(len(datas)//2):
            new_level = []
            for j in range(0, len(nodes), 2):
                if j + 1 >= len(nodes):
                    node = MerkleNode(nodes[j], "", None)
                else:
                    node = MerkleNode(nodes[j], nodes[j+1], None)
                new_level.append(node)
            nodes = new_level
        self.root_node = nodes[0]
    @property
    def root_hash(self):
        return self.root_node.data

如果最后只有單個節(jié)點,那么就將另一個數(shù)據(jù)置空,只計算一個數(shù)據(jù)的哈希。

if j + 1 >= len(nodes):
    node = MerkleNode(nodes[j], "", None)

根節(jié)點的data域就是哈希。

@property
def root_hash(self):
    return self.root_node.data

P2PKH

還有一件事情,我想要再談一談。

大家應(yīng)該還記得,在比特幣中有一個 *腳本(Script)*編程語言,它用于鎖定交易輸出;交易輸入提供了解鎖輸出的數(shù)據(jù)。這個語言非常簡單,用這個語言寫的代碼其實就是一系列數(shù)據(jù)和操作符而已。比如如下示例:

5 2 OP_ADD 7 OP_EQUAL

5, 2, 和 7 是數(shù)據(jù),OP_ADD 和 OP_EQUAL 是操作符。腳本代碼從左到右執(zhí)行:將數(shù)據(jù)依次放入棧內(nèi),當遇到操作符時,就從棧內(nèi)取出數(shù)據(jù),并將操作符作用于數(shù)據(jù),然后將結(jié)果作為棧頂元素。腳本的棧,實際上就是一個先進后出的內(nèi)存存儲:棧里的第一個元素最后一個取出,后面的每一個元素都會放到前一個元素之上。

讓我們來對上面的腳本分部執(zhí)行:

步驟腳本說明
15 2 OP_ADD 7 OP_EQUAL一開始棧為空
252 OP_ADD 7 OP_EQUAL從腳本里面取出 5 放入棧上
35 2OP_ADD 7 OP_EQUAL從腳本里面取出 2 放入棧上
477 OP_EQUAL遇到操作符 OP_ADD, 從棧里取出兩個操作數(shù) 5 和 2,相加后將結(jié)果放回棧上
57 7OP_EQUAL從腳本里面取出 7 放到棧上
6true遇到操作符 OP_EQUAL,從棧里取出兩個操作數(shù)并比較,將比較的結(jié)果放回棧內(nèi),腳本執(zhí)行完畢,為空

OP_ADD 從棧內(nèi)取兩個元素,將這兩個元素進行相加,然后將結(jié)果重新放回棧內(nèi)。OP_EQUAL 從棧內(nèi)取兩個元素,然后對這兩個元素進行比較:如果它們相等,就在棧上放一個 true,否則放一個 false。腳本執(zhí)行的結(jié)果就是棧頂元素:在我們的案例中,如果是 true,那么表明腳本執(zhí)行成功。

現(xiàn)在來看一下在比特幣中,是如何用腳本執(zhí)行支付的:

<signature> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

這個腳本叫做 Pay to Public Key Hash(P2PKH),這是比特幣最常用的一個腳本。它所做的事情就是向一個公鑰哈希支付,也就是說,用某一個公鑰鎖定一些幣。這是比特幣支付的核心:沒有賬戶,沒有資金轉(zhuǎn)移;只有一個腳本檢查提供的簽名和公鑰是否正確。

這個腳本實際存儲為兩個部分:

第一個部分,<signature> <pubkey>,存儲在輸入的 ScriptSig 字段。

第二部分,OP_DUP OP_HASH160 <pubkeyHash> OP_EQUALVERYFY OP_CHECKSIG 存儲在輸出的 ScriptPubKey 里面。

因此,輸出定了解鎖的邏輯,輸入提供解鎖輸出的“鑰匙”。然我們來執(zhí)行一下這個腳本:

步驟腳本
1<signature> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
2<signature><pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
3<signature> <pubkey>OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
4<signature> <pubKey> <pubKey>OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
5<signature> <pubKey> <pubKeyHash><pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
6<signature> <pubKey> <pubKeyHash> <pubKeyHash>OP_EQUALVERIFY OP_CHECKSIG
7<signature> <pubKey>OP_CHECKSIG
8true 或 false

OP_DUP 對棧頂元素進行復(fù)制。OP_HASH160 取棧頂元素,然后用 RIPEMD160 對它進行哈希,再將結(jié)果送回到棧上。OP_EQUALVERIFY 將棧頂?shù)膬蓚€元素進行比較,如果它們不相等,終止腳本。OP_CHECKSIG 通過對交易進行哈希,并使用 <signature> 和 pubKey 來驗證一筆交易的簽名。最后的操作符有點復(fù)雜:它生成了一個修剪后的交易副本,對它進行哈希(因為它是一個被簽名后的交易哈希),然后使用提供的 <signature> 和 pubKey 檢查簽名是否正確。

有了一個這樣的腳本語言,實際上也可以讓比特幣成為一個智能合約平臺:除了將一個單一的公鑰轉(zhuǎn)移資金,這個語言還使得一些其他的支付方案成為可能。

總結(jié)

參考:

[1] transactions2

[2] 本節(jié)完整實現(xiàn)源碼

這就是今天的全部內(nèi)容了!我們已經(jīng)實現(xiàn)了一個基于區(qū)塊鏈的加密貨幣的幾乎所有關(guān)鍵特性。我們已經(jīng)有了區(qū)塊鏈,地址,挖礦和交易。我們還缺少網(wǎng)絡(luò)讓所有的節(jié)點聯(lián)合起來,更多關(guān)于python區(qū)塊鏈挖礦獎勵交易的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python 操作mysql數(shù)據(jù)庫查詢之fetchone(), fetchmany(), fetchall()用法示例

    Python 操作mysql數(shù)據(jù)庫查詢之fetchone(), fetchmany(), fetchall()用法示例

    這篇文章主要介紹了Python 操作mysql數(shù)據(jù)庫查詢之fetchone(), fetchmany(), fetchall()用法,結(jié)合實例形式分析了Python使用pymysql模塊的fetchone(), fetchmany(), fetchall()方法進行mysql數(shù)據(jù)庫查詢的操作技巧,需要的朋友可以參考下
    2019-10-10
  • Python中的列表生成式與生成器學(xué)習(xí)教程

    Python中的列表生成式與生成器學(xué)習(xí)教程

    這篇文章主要介紹了Python中的列表生成式與生成器學(xué)習(xí)教程,Python中的Generator生成器比列表生成式功能更為強大,需要的朋友可以參考下
    2016-03-03
  • Python中使用json.load()和json.loads()加載json數(shù)據(jù)的方法實例

    Python中使用json.load()和json.loads()加載json數(shù)據(jù)的方法實例

    在python編程中,我們經(jīng)常要用到j(luò)son對象作為數(shù)據(jù)交換格式,下面這篇文章主要給大家介紹了關(guān)于Python中使用json.load()和json.loads()加載json數(shù)據(jù)的方法實例,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-08-08
  • 利用python爬取斗魚app中照片方法實例

    利用python爬取斗魚app中照片方法實例

    最近在學(xué)習(xí)python,通過實踐是學(xué)習(xí)的一個好辦法,下面這篇文章就來給大家介紹了關(guān)于利用python爬取斗魚app中照片的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友下面來一起看看吧。
    2017-12-12
  • Python獲取遠程文件大小的函數(shù)代碼分享

    Python獲取遠程文件大小的函數(shù)代碼分享

    這篇文章主要介紹了Python獲取遠程文件大小的函數(shù)代碼分享,需要的朋友可以參考下
    2014-05-05
  • Python對PDF文件的常用操作方法詳解

    Python對PDF文件的常用操作方法詳解

    PDF是Portable?Document?Format的縮寫,這類文件通常使用`.pdf`作為其擴展名。在日常開發(fā)工作中,最容易遇到的就是從PDF中讀取文本內(nèi)容以及用已有的內(nèi)容生成PDF文檔這兩個任務(wù)。本文為大家介紹了幾個Python中常見的PDF操作,需要的可以參考一下
    2022-05-05
  • 詳解設(shè)計模式中的工廠方法模式在Python程序中的運用

    詳解設(shè)計模式中的工廠方法模式在Python程序中的運用

    這篇文章主要介紹了設(shè)計模式中的工廠方法模式在Python程序中的運用,工廠方法模式主張程序在設(shè)計時要可以根據(jù)不同的條件生成各種類的實例,需要的朋友可以參考下
    2016-03-03
  • 一文讀懂Python版本管理工具Pyenv使用

    一文讀懂Python版本管理工具Pyenv使用

    在開發(fā)Python程序的時候,有時候可能需要在不同版本的Python上進行測試。pyenv就是這么一個管理多版本Python的工具,今天給大家分享Python版本管理工具Pyenv使用,感興趣的朋友一起看看吧
    2021-06-06
  • Python 剪繩子的多種思路實現(xiàn)(動態(tài)規(guī)劃和貪心)

    Python 剪繩子的多種思路實現(xiàn)(動態(tài)規(guī)劃和貪心)

    這篇文章主要介紹了Python 剪繩子的多種思路實現(xiàn)(動態(tài)規(guī)劃和貪心),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • django刪除表重建的實現(xiàn)方法

    django刪除表重建的實現(xiàn)方法

    今天小編就為大家分享一篇django刪除表重建的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08

最新評論

三台县| 南澳县| 乾安县| 二连浩特市| 锦屏县| 吉林市| 永仁县| 元朗区| 孟州市| 仁怀市| 荥经县| 和静县| 聂拉木县| 河津市| 昔阳县| 广灵县| 尖扎县| 田东县| 武城县| 瑞金市| 法库县| 张北县| 深水埗区| 金坛市| 黔江区| 隆尧县| 秦皇岛市| 铜鼓县| 诏安县| 衡东县| 息烽县| 贡觉县| 阿拉尔市| 吉林省| 夏津县| 通城县| 甘南县| 乌鲁木齐县| 黑水县| 庆安县| 綦江县|