【问题标题】:Is there a way to use a string of variable names as input to a function?有没有办法使用一串变量名作为函数的输入?
【发布时间】:2020-09-14 01:31:40
【问题描述】:

我想知道这样的事情是否可行(下面的 Python 代码)

def my_function(v1, v2):
    return v1+v2

var1 = 1
var2 = 2

vars = "var1,var2"

print(my_function(vars))

我知道这段代码不起作用,因为该函数需要两个参数,但我想知道的原因是我想设计一个可以更改参数长度的函数。 *args 和 **kwargs 将不起作用,因为我正在调用的函数已经生成。这是我的上下文代码的 sn-p

def construct_transaction(value, chain_id, gas, gas_price, **params):

    # amountIn = w3.toWei(0.1, 'ether')   # << These are the variables I would like to 
    # amountOutMin = 1                    # input into the function below
    # path = [token_0_addr, token_1_addr] # "swapExactTokensForTokens"
    # to_addr = my_addr
    # deadline = 1690528847

    for key in params.keys():
        locals()[key] = params[key]       # variables created from params

    nonce = w3.eth.getTransactionCount(w3.toChecksumAddress(my_addr))

    txn = uniswap_v2_router_contract.functions.swapExactTokensForTokens("amountIn,..,"). \
        buildTransaction({
        'value': 0,
        'chainId': chain_id,
        'gas': gas,
        'gasPrice': gas_price,
        'nonce': nonce,
    })

参数的数量将根据调用的合约和函数而改变。提前致谢。

【问题讨论】:

  • 我不知道我是否正确理解了这个问题,但是请default arguments帮忙?
  • 我不清楚你想做什么。您似乎想从外部强制更改函数的签名(定义标头);这是不可能的。此外,将变量名称作为字符串传递几乎总是显示出设计缺陷。您使用某种迭代(列表、元组、集合等)在单个变量名下传递一组值。
  • 不,很遗憾没有。我想要做的是使用 **params 将参数发送到“construct_transaction”,然后将这些参数发送到“swapExactTokensForTokens”。我的目标是做这样的事情:tx = (contract_name).functions.(function_name)(arguments) 其中contract_name、function_name和arguments可以根据发送到函数的内容而改变。

标签: python function ethereum smartcontracts web3


【解决方案1】:

您可以将函数存储在 dict 中以通过名称访问它们,然后将参数作为 *args 传递:

def execute_fun(my_funs: dict, name: str, args: tuple):
    """
    lookup a function by name from my_funs dict and execute it using the provided args
    """
    return my_funs[name](*args)

def first_fun(a):
    return a + a

def second_fun(a, b):
    return a + b

my_funs = {
    'first_fun': first_fun,
    'second_fun': second_fun
}

execute_fun(my_funs, 'first_fun', (7,)) # 14
execute_fun(my_funs, 'second_fun', (4, 5,)) # 9

这看起来不过,使用类可能会做得更好,因为它会将所有内容放在正确的命名空间中:

class A:

  def first(self, a):
        return a + a

    def second(self, a, b):
        return a + b

    def __getitem__(self, name):
        return getattr(self, name)

    def __call__(self, name, args):
        return self[name](*args)

a = A()
a['first'] # <bound method A.first of <__main__.A object at 0x7fe934541790>>
a('first', (7,)) # 14
a('second', (4, 5,)) # 9

【讨论】:

  • 谢谢,我意识到我使用的是 **kwargs 而不是 *args。感谢 Jan Christoph Terasa 和 Prune 的投入 :)。你的代码为我清除了一切。
猜你喜欢
  • 2022-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多