برنامه نویسی

Vyper: برای حلقه ها و آرایه ها.

Vyper یک زبان پایتونیک است اما از آرایه ها یا رشته های پویا به اندازه پایتون پشتیبانی نمی کند. بنابراین، اگر کسی بخواهد با آنها بازی کند، دستورالعمل های خاصی وجود دارد که باید از آنها پیروی کرد for loops و arrays. در این آموزش، ما قصد داریم از مثال هایی برای درک بهتر نحوه کار کردن چیزها استفاده کنیم.


@external
def iterate_array_variable() -> int128:
    marks: int128[4] = [45, 67, 90, 36]
    result: int128[4] = [0, 0, 0, 0]
    for x in range(4):
        result[x] = marks[x] * 2
    return result[2]

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مثال بالا یک تابع تعریف می کنیم iterate_array_variable که یک متغیر از نوع را برمی گرداند int128. سپس یک آرایه تعریف می کنیم marks که باید حاوی 4 تحت اللفظی نوع int128. result همچنین یک آرایه است که دقیقاً مانند تعریف شده است marks. تنها تفاوت آنها مقادیر موجود در این دو آرایه است [45, 67, 90, 36] و [0, 0, 0, 0]. هدف این تابع، دادن مقادیر جدید به آرایه نتیجه است result[x] = marks[x] * 2.

ما انتظار داریم که تابع به را برگرداند result برای داشتن یک مقدار جدید برای هر تکرار انجام شده. به عنوان مثال، در موقعیت سوم (result[2]، مقدار باید از تغییر کند 0 به 180

تعامل با قرارداد

import sys
from web3 import Web3

# Connect to BSC node (Binance Smart Chain)
bsc_node_url = 'https://data-seed-prebsc-1-s1.binance.org:8545/'  # Replace with your BSC node URL
web3 = Web3(Web3.HTTPProvider(bsc_node_url))

# Set the private key directly (For demonstration purposes only, do not hardcode in production)
private_key = 'Your_private_key'  # Replace with your actual private key
account = web3.eth.account.from_key(private_key)

# Contract ABI
contract_abi = [
    Your_abi
]
# Contract address
contract_address = web3.to_checksum_address('your_contract_address')  # Replace with your contract's address

# Create contract instance
contract = web3.eth.contract(address=contract_address, abi=contract_abi)


# Function to set a choice
def call_iterate_array_variable():
    nonce = web3.eth.get_transaction_count(account.address)
    tx = contract.functions.iterate_array_variable().build_transaction({
        'chainId': 97,  # BSC testnet
        'gas': 3000000,
        'gasPrice': web3.to_wei('5', 'gwei'),
        'nonce': nonce,
    })
    signed_tx = web3.eth.account.sign_transaction(tx, private_key)
    tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction)
    receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
    result = contract.functions.iterate_array_variable().call()
    return result

def main():
    result = call_iterate_array_variable()
    print(f'Result of the calculation: {result}')

if __name__ == "__main__":
    main()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نتیجه

نتایج ترمینال

تکرار از طریق مقادیر یک متغیر آرایه

y: public(int128)
@external
def iterate_array_variable() -> int128:
    marks: int128[4] = [45, 67, 90, 36]
    for x in marks:
        self.y = x
    return self.y
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مثال بالا، ما مقادیر متغیر را تکرار می کنیم marks. انتظار داریم تابع برگردد 36 زیرا آخرین مقداری خواهد بود که به آن اختصاص داده شده است y بعد از تکرار

ممکن است کسی بپرسد، اگر بخواهیم مقدار معینی را از چنین آرایه ای برگردانیم، چه؟ پاسخ در نهفته است assert عبارتی که برای عملیات بولی استفاده می شود.

y: public(int128)

@external
def get_mark(index: int128) -> int128:
    marks: int128[4] = [45, 67, 90, 36]
    assert 0 <= index, "Index out of lower limit"
    assert index < 4, "Index out of upper limit"
    self.y = marks[index]
    return self.y
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مثال بالا، کاملاً مشهود است که می‌توانیم به صراحت مقداری را که می‌خواهیم به آن دسترسی داشته باشیم، با ارائه اندیس آن مقدار از یک آرایه تعیین کنیم. assert 0 <= 4 اطمینان حاصل می کند که شاخص بزرگتر یا مساوی صفر است. در غیر این صورت اجرای قرارداد خواهد بود برگردانده شد با پیام خطای “ایندکس از حد پایین تر” assert index < 4 رفتاری مشابه اما با منطق متفاوت دارد.

تعامل با قرارداد

from web3 import web3

"""
.......
......
Other code here
......
....
"""

# Create contract instance
contract = web3.eth.contract(address=contract_address, abi=contract_abi)


# Function to set a choice
def call_get_mark(index):
    nonce = web3.eth.get_transaction_count(account.address)
    tx = contract.functions.get_mark(index).build_transaction({
        'chainId': 97,  # BSC testnet
        'gas': 3000000,
        'gasPrice': web3.to_wei('5', 'gwei'),
        'nonce': nonce,
    })
    signed_tx = web3.eth.account.sign_transaction(tx, private_key)
    tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction)
    receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
    result = contract.functions.get_mark(index).call()
    return result

def main():
    index = int(input("Enter the index (0 to 3): "))
    result = call_get_mark(index)
    print(f'Result of the calculation: {result}')

if __name__ == "__main__":
    main()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همچنین می توانیم روی یک آرایه تحت اللفظی تکرار کنیم:

# declaring variable y
y: public(int128)

@external
def non_dictated() -> int128:
    for x in [34, 76, 89, 45]:
        self.y = x
    return self.y
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد بالا باز خواهد گشت 45 زیرا آخرین مقداری است که در متغیر ذخیره می شود y.

تکرار محدوده

در همان ابتدای این مقاله، یک مورد کاربری از محدوده را دیدیم، for x in range(4):. محدوده ها با استفاده از range تابع. مثال بالا از یک ساختار پیروی می کند. for i in range(STOP): جایی که STOP یک عدد صحیح واقعی بزرگتر از صفر است.

استفاده دیگر از محدوده می تواند با START و STOP محدوده

for i in range(START, STOP):
    ...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اینجا، START و STOP اعداد صحیح تحت اللفظی هستند، با STOP ارزشی بیشتر از START. i آغاز می شود به عنوان START و یک افزایش می یابد تا برابر شود STOP.

مثال


@external
def iterate_array_variable() -> int128:
    marks: int128[4] = [45, 67, 90, 36]
    result: int128[4] = [0, 0, 0, 0]
    for x in range(1, 2):
        result[x] = marks[x] * 2
    return result[3]

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در هنگام اجرا، کد بالا با خطای شاخص مشخص شده توسط result[3]، جایگاه چهارم، از دامنه دو موقعیت از رتبه دوم تا سوم فراتر می رود.

مثال مهم دیگر این است که؛

for i in range(stop, bound=N):
    ...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا، stop می تواند یک متغیر با نوع عدد صحیح، بزرگتر از صفر باشد. N باید یک ثابت زمان کامپایل باشد. i به صورت صفر شروع می شود و یک افزایش می یابد تا زمانی که برابر با توقف شود. اگر توقف بزرگتر از N باشد، اجرا در زمان اجرا برمی گردد. در موارد خاص، ممکن است تضمینی نداشته باشید که توقف کمتر از N است، اما همچنان می خواهید از احتمال بازگشت زمان اجرا جلوگیری کنید. برای انجام این کار، از bound= کلمه کلیدی در ترکیب با min(stop, N) به عنوان آرگومان محدوده، مانند range(min(stop, N), bound=N). این برای موارد استفاده مانند تقسیم کردن عملیات در آرایه های بزرگتر در چندین تراکنش مفید است.

برای درک بهتر این موضوع، ابتدا باید درک کنیم ثابت زمان کامپایل و بازگشت زمان اجرا.

بازگشت زمان اجرا به رفتار قرارداد در هنگام مواجهه با خطا در حین اجرا اشاره دارد. اگر شرطی در قرارداد محقق نشود یا استثناء شود، عقد به حالت قبلی قبل از معامله باز می گردد. این تضمین می کند که هیچ تغییر جزئی یا اشتباهی در وضعیت بلاک چین ایجاد نمی شود. به عنوان مثال، استفاده از عبارات assert یا require می‌تواند در صورت عدم موفقیت شرط، باعث بازگشت مجدد شود.

# compile-time constant
MAX_SUPPLY: constant(uint256) = 1000000

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

# if amount is not greater than zero, 
# the transaction will revert at runtime, 
# ensuring the contract state remains unchanged.

@external
def transfer(amount: uint256):
    assert amount > 0, "Amount must be greater than zero"
    # transfer logic

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما قصد داریم از چهار مثال زیر استفاده کنیم تا به طور کامل بفهمیم که چگونه می توان از محدوده به این روش استفاده کرد. در هر دو مثال، ثابت زمانی کامپایل N است 4. آنچه تغییر می کند این است stop ارزش. جفت اول دارای مقدار توقف است 2 و دیگری دارای مقدار توقف است 84.

جفت اول


latest_index: public(int128)

N: constant(int128) = 4  # compile time constant

@external
def process_chunk() -> int128:
    for i in range(2, bound=N):
        self.latest_index = i
    return self.latest_index

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید


latest_index: public(int128)

N: constant(int128) = 4  # compile time constant

@external
def process_chunk() -> int128:
    for i in range(min(2, N), bound=N):
        self.latest_index = i
    return self.latest_index
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

وقتی دو قرارداد فوق را اجرا می کنیم، latest_index مقدار برگشتی است 1.

جفت دوم


latest_index: public(int128)

N: constant(int128) = 4  # compile time constant

@external
def process_chunk() -> int128:
    for i in range(84, bound=N):
        self.latest_index = i
    return self.latest_index

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید


latest_index: public(int128)

N: constant(int128) = 4  # compile time constant

@external
def process_chunk() -> int128:
    for i in range(min(84, N), bound=N):
        self.latest_index = i
    return self.latest_index

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

وقتی اولین قرارداد را در این جفت اجرا می کنیم، a را می اندازد ContractLogicError: Execution Reverted.

با این حال، آخرین قرارداد مقدار last_index را برمی گرداند 3 هنگام اجرا

توضیح

در اولین جفت مثال، ما 1 را به عنوان مقدار بازگشتی دریافت می کنیم، فقط به این دلیل stop مقدار از ثابت تجاوز نمی کند N.

در جفت دوم، می‌توانیم ببینیم که در جایی که مثال دوم به خوبی کامپایل می‌شود، با خطا مواجه می‌شویم. دلیل این امر استفاده از min(stop, N) به عنوان یک استدلال به سادگی مقدار توقف را نسبت به مقدار به حداقل می رساند N ارائه شده است. بنابراین، حداقل مقدار ممکن از stop در این صورت خواهد بود 4 از این رو مقدار شاخص را برمی گرداند 3.

برای اطلاعات بیشتر، لطفاً از مستندات رسمی vyper دیدن کنید و همچنین مقاله قبلی خود را برای درک عمیق تر vyperlang توصیه می کنم. اگر این مقاله برای شما مفید بود، خوشحال می شوم اگر به من قلب بدهید. برای ادامه مطلب فالو کنید متشکرم!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا