Python 对象或闭包-何时使用?
我可以定义对象并指定属性和方法:Python 对象或闭包-何时使用?,python,oop,functional-programming,Python,Oop,Functional Programming,我可以定义对象并指定属性和方法: class object: def __init__(self,a,b): self.a = a self.b = b def add(self): self.sum = self.a + self.b def subtr(self): self.fin = self.sum - self.b def getpar(self): return self
class object:
def __init__(self,a,b):
self.a = a
self.b = b
def add(self):
self.sum = self.a + self.b
def subtr(self):
self.fin = self.sum - self.b
def getpar(self):
return self.fin
obj = object(2,3)
obj.add()
obj.subtr()
obj.getpar()
或者通过定义闭包来提供相同的功能:
def closure(a,b):
par = {}
def add():
par.update({'sum':a+b})
def subtr():
par.update({'fin':par['sum']-b})
def getpar():
return par['fin']
return {'add':add,'subtr':subtr,'getpar':getpar}
clos = closure(2,3)
clos['add']()
clos['subtr']()
clos['getpar']()
我认为对象语法在大多数观众看来会更清晰,但在某些情况下,使用闭包在语义上更可取吗?在Python中,闭包比更常见的对象更难调试和使用(您必须将可调用项保存在某个地方,使用goofy符号
clos['add']
etc,…)。例如,如果在结果中发现一些奇怪的东西,就不可能访问<代码>和>代码>…调试这种事情可能非常困难;-)
唯一真正的补偿优势是简单性——但它基本上只适用于真正简单的情况(当您有三个内部函数的可调用项时,我认为您在这方面做得太过分了)
可能是非常强大的保护(vs对象对类和实例对象的“按约定”保护),或者Javascript程序员可能更熟悉,在边缘情况下可能需要使用闭包而不是类和实例,但在实践中,我并没有发现自己在这种假设的优势似乎实际适用的情况下——所以我只在非常简单的情况下使用闭包;-) 类的调用语法看起来更好,您可以对类进行子类化。闭包还涉及重复要在
return
语句中公开的所有名称。不过,如果您想拥有比通常的下划线前缀约定更隐蔽的真正私有的方法,那么这也许是可以的,您应该使用最清楚地表达您想要实现的内容的版本
在给出的示例中,我认为对象版本更清晰,因为它似乎是在用状态发生变化的对象建模。查看使用该值的代码,对象版本似乎表达了明确的意图,而闭包版本似乎有一些操作(索引和“魔术”字符串)与此无关
在Python中,当需要的是类似于函数的东西,并且可能需要捕获某些状态时,我倾向于使用基于闭包的方法
def tag_closure(singular, plural):
def tag_it(n):
if n == 1:
return "1 " + singular
else:
return str(n) + " " + plural
return tag_it
t_apple = tag_closure("apple", "apples")
t_cherry = tag_closure("cherry", "cherries");
print t_apple(1), "and", t_cherry(15)
这可能比以下内容更清楚:
class tag_object(object):
def __init__(self, singular, plural):
self.singular = singular
self.plural = plural
def tag(self, n):
if n == 1:
return "1 " + self.singular
else:
return str(n) + " " + self.plural
t_apple = tag_object("apple", "apples")
t_cherry = tag_object("cherry", "cherries");
print t_apple.tag(1), "and", t_cherry.tag(15)
作为经验法则:如果这个东西实际上只是一个函数,它只捕获静态状态,那么考虑一个闭包。如果该对象打算具有可变状态,和/或具有多个函数,请使用类
另一种说法是:如果要创建闭包的dict,基本上是手工复制类机制。最好将它留给专门设计的语言结构来完成。我所能看到的使用闭包的唯一真正原因是,如果您想要一个相当有力的保证,即对象/闭包的用户没有访问隐藏变量的权限 大概是这样的:
class Shotgun:
def __init__(self):
me = {}
me['ammo'] = 2
def shoot():
if me['ammo']:
me['ammo'] -= 1
print "BANG"
else:
print "Click ..."
self.shoot = shoot
s = Shotgun()
s.shoot()
s.shoot()
s.shoot()
我做了一个评论,大意是使用函数属性,闭包可以使用与类相同的语法,因为函数是python中的对象。所有内部变量也可以像类方法一样访问 我很好奇这种方法是否会带来我不知道的坏事
def closure(a, b):
def add():
closure.sum = a + b
def subtr():
closure.fin = closure.sum - b
def getpar():
return closure.fin
closure.add = add;
closure.subtr = subtr
closure.getpar = getpar
return closure
clo = closure(2,3)
clo.add()
clo.subtr()
print(clo.getpar())
print(clo.sum)
print(clo.fin)
另见:)是的,斯蒂芬应该在Qc Na下学习。他还在学学徒吗?:)我不确定我们是否可以依赖闭包来将变量私有化。你可以用
s.shoot.func\u closure[0]来改装s=Shotgun()
。单元格内容['ammo']=1e20
你说得对。在任何安全性上依赖于此都不是一个好主意。挖掘闭包听起来不像使用“obj.variable=”符号访问类对象的内部结构那么简单。至少是这样,我不经常使用子类,但这是Objects的一个有力论据。我很好奇你对我下面的评论有什么看法,其中函数属性用于创建与对象相同的语法,再加上not(轻松)的附加便利性除非在返回语句中显式包含函数内部结构,否则将其公开。+1用于强调代码的可读性/清晰性作为决策点。如果使用函数属性而不是字典,则闭包与类的用法相同。我会在下面写一个答案。