如何在 Python 中将参数绑定到函数?

2024-11-28 08:37:00
admin
原创
195
摘要:问题描述:如何将参数绑定到 Python 函数,以便稍后可以在没有参数(或使用更少的附加参数)的情况下调用它?例如:def add(x, y): return x + y add_5 = magic_function(add, 5) assert add_5(3) == 8 我这里需要什么magic...

问题描述:

如何将参数绑定到 Python 函数,以便稍后可以在没有参数(或使用更少的附加参数)的情况下调用它?

例如:

def add(x, y):
    return x + y

add_5 = magic_function(add, 5)
assert add_5(3) == 8

我这里需要什么magic_function


在框架和库中,经常会发生这种情况:人们在尝试向回调提供参数时意外地立即调用函数:例如on_event(action(foo))。解决方案是使用此处描述的技术之一将foo参数绑定到。例如,请参阅如何在 Tkinter 中将参数传递给按钮命令?和在 Python 中使用字典作为 switch 语句。action

但是,有些 API 允许您单独传递要绑定的参数,并会为您完成绑定。值得注意的是,标准库中的线程 API 就是这样工作的。请参阅在调用 Thread.start 之前线程开始运行。如果您尝试像这样设置自己的 API,请参阅如何编写一个简单的回调函数?。

显式绑定参数也是避免使用闭包时后期绑定导致的问题的一种方法。例如,当循环或列表推导式lambda内部for产生计算相同结果的单独函数时,就会出现此问题。请参阅lambda 函数闭包捕获了什么?和在循环(或推导式)中创建函数(或 lambda)。


解决方案 1:

functools.partial返回一个可调用函数,其中包装了部分或全部参数并被冻结。

import sys
import functools

print_hello = functools.partial(sys.stdout.write, "Hello world
")

print_hello()
Hello world

上述用法与以下用法等效lambda

print_hello = lambda *a, **kw: sys.stdout.write("Hello world
", *a, **kw)

解决方案 2:

使用functools.partial

>>> from functools import partial
>>> def f(a, b):
...     return a+b
... 
>>> p = partial(f, 1, 2)
>>> p()
3
>>> p2 = partial(f, 1)
>>> p2(7)
8

解决方案 3:

如果functools.partial没有的话就可以轻松模拟:

>>> make_printer = lambda s: lambda: sys.stdout.write("%s
" % s)
>>> import sys
>>> print_hello = make_printer("hello")
>>> print_hello()
hello

或者

def partial(func, *args, **kwargs):
    def f(*args_rest, **kwargs_rest):
        kw = kwargs.copy()
        kw.update(kwargs_rest)
        return func(*(args + args_rest), **kw) 
    return f

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

p = partial(f, 1, 2)
print p() # -> 3

p2 = partial(f, 1)
print p2(7) # -> 8

d = dict(a=2, b=3)
p3 = partial(f, **d)
print p3(), p3(a=3), p3() # -> 5 6 5

解决方案 4:

lambdas 允许您创建一个具有更少参数的新未命名函数并调用该函数:

>>> def foobar(x, y, z):
...     print(f'{x}, {y}, {z}')
... 
>>> foobar(1, 2, 3)  # call normal function
1, 2, 3
>>> bind = lambda x: foobar(x, 10, 20)  # bind 10 and 20 to foobar
>>> bind(1)
1, 10, 20
>>> bind = lambda: foobar(1, 2, 3)  # bind all elements
>>> bind()
1, 2, 3

你也可以使用functools.partial。如果你打算在函数调用中使用命名参数绑定,这也适用:

>>> from functools import partial
>>> barfoo = partial(foobar, x=10)
>>> barfoo(y=5, z=6)
10, 5, 6

请注意,如果从左侧绑定参数,则需要按名称调用参数。如果从右侧绑定,则它会按预期工作。

>>> barfoo(5, 6)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foobar() got multiple values for argument 'x'
>>> f = partial(foobar, z=20)
>>> f(1, 1)
1, 1, 20

解决方案 5:

这也行得通:

def curry(func, *args):
    def curried(*innerargs):
       return func(*(args+innerargs))
    curried.__name__ = "%s(%s, ...)" % (func.__name__, ", ".join(map(str, args)))
    return curried

>>> w=curry(sys.stdout.write, "Hey there")
>>> w()
Hey there

解决方案 6:

在 Python 中,函子可以这样定义。它们是可调用对象。“绑定”只是设置参数值。

class SomeFunctor( object ):
    def __init__( self, arg1, arg2=None ):
        self.arg1= arg1
        self.arg2= arg2
    def __call___( self, arg1=None, arg2=None ):
        a1= arg1 or self.arg1
        a2= arg2 or self.arg2
        # do something
        return

你可以做类似的事情

x= SomeFunctor( 3.456 )
x( arg2=123 )

y= SomeFunctor( 3.456, 123 )
y()

解决方案 7:

问题一般询问绑定参数,但所有答案都是关于函数的。如果您想知道,partial也可以使用类构造函数(即使用类而不是函数作为第一个参数),这对于工厂类很有用。您可以按如下方式执行此操作:

from functools import partial

class Animal(object):
    def __init__(self, weight, num_legs):
        self.weight = weight
        self.num_legs = num_legs
        
animal_class = partial(Animal, weight=12)
snake = animal_class(num_legs = 0)
print(snake.weight) # prints 12
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2098  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1460  
  建筑行业正处于数字化转型的关键时期,建筑产品生命周期管理(PLM)系统的实施对于提升项目效率、质量和协同性至关重要。特别是在 2025 年,基于建筑信息模型(BIM)的项目进度优化工具成为众多建筑企业关注的焦点。这些工具不仅能够整合项目全生命周期的数据,还能通过精准的分析和模拟,为项目进度管理提供强大支持。BIM 与建...
plm是什么软件   13  
  PLM系统开发的重要性与现状PLM(产品生命周期管理)系统在现代企业的产品研发、生产与管理过程中扮演着至关重要的角色。它贯穿产品从概念设计到退役的整个生命周期,整合了产品数据、流程以及人员等多方面的资源,极大地提高了企业的协同效率和创新能力。通过PLM系统,企业能够实现产品信息的集中管理与共享,不同部门之间可以实时获取...
国产plm软件   15  
  PLM(产品生命周期管理)系统在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和技术的飞速发展,企业对PLM系统的迭代周期优化需求日益迫切。2025年敏捷认证对项目管理提出了新的要求,其中燃尽图作为一种强大的可视化工具,在PLM系统迭代周期优化中有着广泛且重要的应用。深入探讨这些应用,对于提升企业的项...
plm系统主要干什么的   16  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用