首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python --使用“部分”来解决后期绑定问题--成本与收益之间的关系?

Python --使用“部分”来解决后期绑定问题--成本与收益之间的关系?
EN

Stack Overflow用户
提问于 2014-05-01 01:28:09
回答 3查看 1K关注 0票数 2

备注:我是在问是否有一种Pythonic方法可以做到这一点(使用默认的args似乎比使用部分方法要少),如果这两种方法都有很大的限制(“成本”--我不认为时间会有很大的不同,但也许还有其他的限制,我没有看到平衡倾向于一种方法而不是另一种方法)。

我正试图理解在后期绑定的情况下使用“部分”的成本,因为lambda是不可行的。我创建了一些示例代码基于本指南来举例说明这一点。

由于延迟绑定,以下内容无法正常工作:

代码语言:javascript
复制
def create_thingies():
    thingies = []
    for i in range(1,6):
        def thingy(x):
            print("Some output", i)
            return i ** (x * i)
        thingies.append(thingy)
    return thingies

results=[]
for thingy in create_thingies():
    results.append(thingy(2))
print(results)

输出:

代码语言:javascript
复制
Some output 5
Some output 5
Some output 5
Some output 5
Some output 5
[9765625, 9765625, 9765625, 9765625, 9765625]

使用“部分”可以避免这个问题,但代价是什么呢?

代码语言:javascript
复制
from functools import partial
def create_thingies():
    thingies = []
    for i in range(1,6):
        def thingy(i, x):
            print("Some output", i)
            return i ** (x * i)
        thingies.append(partial(thingy, i))
    return thingies

results=[]
for thingy in create_thingies():
    results.append(thingy(2))
print(results)

输出:

代码语言:javascript
复制
Some output 1
Some output 2
Some output 3
Some output 4
Some output 5
[1, 16, 729, 65536, 9765625]

在这里,我看到了很多关于lambda和的讨论,但是在这样的情况下,lambda将不能很好地工作(一个非常复杂的函数),如果(包含更多表达式的函数)是部分的话,或者还有更好的方法来强迫它成为lambda表达式呢?

EN

回答 3

Stack Overflow用户

发布于 2014-05-01 02:44:56

使用partial,不需要为i的每个值定义一次thingy,因为thingy不使用任何空闲/全局变量,而只使用它的参数。

代码语言:javascript
复制
from functools import partial

def thingy(i, x):
    print("Some output", i)
    return i ** (x * i)

thingies = [partial(thingy, i) for i in range(1,6)]
results = [th(2) for th in thingies]
print(results)

至于成本,你应该分析一下,看看性能是否可以接受。

下面是一个比较三个选项的快速测试:

代码语言:javascript
复制
import timeit

# The fastest: define a function using a default parameter value
print timeit.timeit('results = [ th(2) for th in create_thingies()]', '''
def create_thingies():
    thingies = []
    for i in range(1,6):
        def thingy(x,i=i):
            #print("Some output", i)
            return i ** (x * i)
        thingies.append(thingy)
    return thingies
''')

# The slowest, but IMO the easiest to read.
print timeit.timeit('results = [ th(2) for th in create_thingies()]', '''
def create_thingies():
    from functools import partial
    def thingy(i,x):
        #print("Some output", i)
        return i ** (x * i)
    return [partial(thingy, i) for i in range(1,6)]
''')

# Only a little slower than the first
print timeit.timeit('results = [ th(2) for th in create_thingies()]', '''
def create_thingies():
    def make_thingy(i):
        def thingy(x):
            #print("Some output", i)
            return i ** (x * i)
        return thingy
    thingies = [make_thingy(i) for i in range(1,6)]
    return thingies
''')
票数 5
EN

Stack Overflow用户

发布于 2014-05-01 01:35:43

使用默认参数nalue在函数创建时绑定值:

代码语言:javascript
复制
def thingy(x, i=i):
    print("Some output", i)
    return i ** (x * i)
票数 3
EN

Stack Overflow用户

发布于 2014-05-01 03:08:27

有几种方法可以进行早期绑定。一些最流行的是默认的args、partial和maker函数。至少在我的机器上,使用我的版本的python,它们所花费的时间大致相同。

下面是三种方法中的每一种方法的示例:

代码语言:javascript
复制
import time
from functools import partial
from contextlib import contextmanager

@contextmanager
def timer(what):
    t1 = time.time()
    yield
    print "%-30s: %5d millis" % (what, (time.time() - t1) * 1e3)

N = 5000

print
with timer('create bound'):
    thingies = []
    for i in xrange(N):
        def thingy(x, i=i):
            return i ** (x * i)
        thingies.append(thingy)
with timer('eval bound'):
    for t in thingies:
        t(2)

with timer('create partial'):
    def thingy(i, x):
        return i ** (x * i)
    thingies = [partial(thingy, i) for i in xrange(N)]
with timer('eval partial'):
    for t in thingies:
        t(2)

with timer('create maker'):
    def make_thingy(i):
        def thingy(x):
            return i ** (x * i)
        return thingy
    thingies = [make_thingy(i) for i in xrange(N)]
with timer('eval maker'):
    for t in thingies:
        t(2)

下面是我观察到的时间(Python2.7.6+ Windows + Haswell):

代码语言:javascript
复制
create bound                  :     5 millis
eval bound                    :  1861 millis
create partial                :     2 millis
eval partial                  :  1832 millis
create maker                  :     2 millis
eval maker                    :  1829 millis

请注意,创建绑定方法的代价更高,但对于所有3个版本来说,调用开销都非常接近。

我通常使用部分函数和maker函数的混合,这取决于给定代码中哪一个最清晰。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23400785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档