还有更多的';pythonic';写这个闭包的方法?

还有更多的';pythonic';写这个闭包的方法?,python,closures,Python,Closures,在JavaScript中,我可以编写如下函数: function counter() { foo = 0; function increment() { foo += 1 console.log(foo); } function printVal() { console.log(foo); } return { increment: increment, printVal: printV

在JavaScript中,我可以编写如下函数:

function counter() {
    foo = 0;
    function increment() {
    foo += 1
    console.log(foo);
  }
  function printVal() {
    console.log(foo);
  }

  return {
                increment: increment,
          printVal: printVal,
                  }    
}

func = counter();

func.increment()
func.increment()
func.printVal()
# this is the tracked function
def add2(a, b):
    return a + b

# this is the count tracker
def counterize(func):
    c = [0]
    def counter_func(*args, **kw):
        c[0] += 1
        counter_func.count = c[0]
        return func(*args, **kw)
    return counter_func


cadd2 = counterize(add2)

print(cadd2(1, 2))
print(cadd2(3, 4))
print('Called %s times' % cadd2.count)

>>>
3
7
Called 2 times
我想尝试使用python实现类似的函数。特别是如何通过外部函数的返回访问两个内部函数

下面是一个python版本,可以正常工作,但看起来很有趣:

def counter():
    foo = {'bar': 0}
    def increment():
        foo['bar'] += 1
        return foo['bar']
    def printVal():
        return foo['bar']
    return {'increment': increment, 'printVal': printVal}

func = counter()
func['increment']()
func['printVal']()

有没有更优雅或“pythonic”的方法来编写这样的闭包?

只需实现
\uuu getitem\uuuu

class Foo:
    class_attributes = {'a': 3,
                        'b': 5}

    def __getitem__(self, name):
        return Foo.class_attributes[name]


f = Foo()
print f['a']
输出:

3

只需实现
\uuu getitem\uuuu

class Foo:
    class_attributes = {'a': 3,
                        'b': 5}

    def __getitem__(self, name):
        return Foo.class_attributes[name]


f = Foo()
print f['a']
输出:

3

我认为您想要实现的是以下示例:

def makeInc(x):
  def inc(y):
     # x is "attached" in the definition of inc
     return y + x

  return inc

incOne = makeInc(1)
incFive = makeInc(5)

incOne (5) # returns 6
incFive(5) # returns 10

您需要创建闭包的pythonic方法。上面的例子演示了如何做到这一点

我认为您想要实现的是以下示例:

def makeInc(x):
  def inc(y):
     # x is "attached" in the definition of inc
     return y + x

  return inc

incOne = makeInc(1)
incFive = makeInc(5)

incOne (5) # returns 6
incFive(5) # returns 10

您需要创建闭包的pythonic方法。上面的例子演示了如何做到这一点

Python在闭包中不如其他语言强大。首先,它只支持读取“闭合”变量,其次,
return
语句使它有点笨拙

另一方面,它对于类非常简洁,因此如果您想要一个具有两个函数的数据成员,我将使用一个类:

class Counter:
    def __init__(self, c=0):
        self.count = c
    def increment(self):
        self.count += 1
    def printVal(self):
        return self.count


c = Counter()
c.increment()
print(c.printVal())
我敢说,在这种情况下,这将是蟒蛇式的方式

编辑

在看到您关于跟踪函数调用的评论后,我添加了以下内容。您可以通过闭包来实现,如下所示:

function counter() {
    foo = 0;
    function increment() {
    foo += 1
    console.log(foo);
  }
  function printVal() {
    console.log(foo);
  }

  return {
                increment: increment,
          printVal: printVal,
                  }    
}

func = counter();

func.increment()
func.increment()
func.printVal()
# this is the tracked function
def add2(a, b):
    return a + b

# this is the count tracker
def counterize(func):
    c = [0]
    def counter_func(*args, **kw):
        c[0] += 1
        counter_func.count = c[0]
        return func(*args, **kw)
    return counter_func


cadd2 = counterize(add2)

print(cadd2(1, 2))
print(cadd2(3, 4))
print('Called %s times' % cadd2.count)

>>>
3
7
Called 2 times
但这在Python中并不惯用。在函数对象中保持
count
也是一个很好的技巧,但事实就是这样。诡计。另一方面,在LISP或Scala中,闭包会更自然,但我认为不可能将
计数作为字段,而是将其与结果一起返回

我要说的是,在这种情况下,惯用Python代码也是通过类编写的,在我看来,它更容易理解,并且代码长度相同:

class Counterize:
    def __init__(self, func):
        self.func = func
        self.count = 0
    def __call__(self, *args, **kwargs):
        self.count += 1
        return self.func(*args, **kwargs)


cadd2 = Counterize(add2)
print(cadd2(1, 2))
print(cadd2(3, 4))
print('Called %s times' % cadd2.count)

结果是一样的。
\uuuu call\uuuu
的目的是允许通过使用括号调用将对象视为函数。

Python不像闭包中的其他语言那样强大。首先,它只支持读取“闭合”变量,其次,
return
语句使它有点笨拙

另一方面,它对于类非常简洁,因此如果您想要一个具有两个函数的数据成员,我将使用一个类:

class Counter:
    def __init__(self, c=0):
        self.count = c
    def increment(self):
        self.count += 1
    def printVal(self):
        return self.count


c = Counter()
c.increment()
print(c.printVal())
我敢说,在这种情况下,这将是蟒蛇式的方式

编辑

在看到您关于跟踪函数调用的评论后,我添加了以下内容。您可以通过闭包来实现,如下所示:

function counter() {
    foo = 0;
    function increment() {
    foo += 1
    console.log(foo);
  }
  function printVal() {
    console.log(foo);
  }

  return {
                increment: increment,
          printVal: printVal,
                  }    
}

func = counter();

func.increment()
func.increment()
func.printVal()
# this is the tracked function
def add2(a, b):
    return a + b

# this is the count tracker
def counterize(func):
    c = [0]
    def counter_func(*args, **kw):
        c[0] += 1
        counter_func.count = c[0]
        return func(*args, **kw)
    return counter_func


cadd2 = counterize(add2)

print(cadd2(1, 2))
print(cadd2(3, 4))
print('Called %s times' % cadd2.count)

>>>
3
7
Called 2 times
但这在Python中并不惯用。在函数对象中保持
count
也是一个很好的技巧,但事实就是这样。诡计。另一方面,在LISP或Scala中,闭包会更自然,但我认为不可能将
计数作为字段,而是将其与结果一起返回

我要说的是,在这种情况下,惯用Python代码也是通过类编写的,在我看来,它更容易理解,并且代码长度相同:

class Counterize:
    def __init__(self, func):
        self.func = func
        self.count = 0
    def __call__(self, *args, **kwargs):
        self.count += 1
        return self.func(*args, **kwargs)


cadd2 = Counterize(add2)
print(cadd2(1, 2))
print(cadd2(3, 4))
print('Called %s times' % cadd2.count)

结果是一样的。
\uuuu call\uuuu
的目的是允许通过使用括号调用的方式将对象视为函数。

在这种情况下,您可能需要使用
集合.计数器
对象,或者只是编写一个类。首先,你应该问问自己为什么要在JS中使用闭包:闭包通常是类行为的替代品。在python的情况下,您确实可以使用
来建模记帐行为。你的两个函数变成了真正的方法。在这种情况下,你可能想使用
集合。Counter
对象,或者只是编写一个类。你应该问问自己,为什么要在JS中使用闭包:闭包通常是类行为的替代品。在python的情况下,您确实可以使用
来建模记帐行为。你的两个函数都变成了实方法。这里的所有Foo实例都会使用相同的class_属性吗?在本例中会。可以通过实现构造函数来定义每个实例的类\属性。在这里,相同的类\属性会用于所有Foo实例吗?在本例中,会。可以通过实现构造函数来定义每个实例的class_属性。谢谢,我希望使用闭包,因为我正在努力学习更多的函数技术,但这似乎是目前为止最好的解决方案。我想做的更大的事情是有一个计数器,我可以用来跟踪函数被调用的次数。谢谢,我希望使用闭包,因为我正在努力学习更多的函数技术,但这看起来是迄今为止最好的解决方案。我想做的是有一个计数器,可以用来跟踪函数被调用的次数。