在就地修改的方法中返回语句

时间:2015-10-25 11:18:42

标签: python return in-place

假设我想要一个采用list的简单方法,并通过向其添加5来就地修改它。以下是执行此操作的两种方法,但ret(l)会返回,而no_ret(l)则不会。

def ret(l): 
   l.append(5) 
   return l 


def no_ret(l):
   l.append(5)

哪种方法更pythonic?我猜no_ret()因为如果方法是用于就地修改,那么就没有必要返回,因为我们已经有了对被修改对象的引用。

他们如何在时间和空间效率方面进行比较?

  • 对于时间,我认为ret(l)较慢,因为return语句会增加额外的开销。
  • 对于空间,我认为它们是相同的,因为ret()只返回一个引用(内存地址),所以没有使用新的内存。

我注意到Python提供了就地非返回实例方法sort()和非就地返回静态方法sorted()。但是,我不能使我的就地方法成为像list这样的默认类的实例方法。

2 个答案:

答案 0 :(得分:2)

您不应该做的第一件事是使用您自己的方法复制现有功能 - 但是,我假设您只是给出一个示例,而这不是您计划运行的实际代码。

Python中的所有方法都返回一个值。如果方法没有return语句,则返回None

任何就地修改但不返回的函数;不应该返回一个值。这是有道理的,因为它是“正常”就地方法的工作方式。

正确的实施方式是:

def do_something(foo, bar):
   foo.do_something_inplace(bar)
   return None # or simply, return

空白返回与return None相同,但请记住 - 显式优于隐式。

关于空间和时间效率的另一个问题,这完全取决于实际进行替换的方法的实现。在您的示例中编写内置方法的代理时,“速度惩罚”可以忽略不计。

答案 1 :(得分:0)

在评估 pythonic 某些代码的方式时,我们应该查看标准库。两个可变对象是:

list使用就地方法append

mylist = [1,2,3]
mylist.append(5).append(3) # Throws error 'NoneType' object has no attribute 'append'

dict使用就地方法update

mydict={}
mydict.update(mydict).update(mydict) # Throws error 'NoneType' object has no attribute 'update'

我们可以得出结论,就地方法应该返回None

性能考虑因素:

<强> test.py

def ret(l): 
   l.append(5) 
   return l

def no_ret(l):
   l.append(5)

def test_ret():
    l=[]
    for i in xrange(100000):
        ret(l)

def test_no_ret():
    l=[]
    for i in xrange(100000):
        no_ret(l)

%timeit的IPython中:

In [3]: %timeit test_ret()
10 loops, best of 3: 163 ms per loop

In [4]: %timeit test_no_ret()
10 loops, best of 3: 161 ms per loop

非返回方法比在C-Python中返回更快。

编辑发表评论

你可以在python中使任何方法成为类的实例方法:

class MyObject(object):
    def __init__(self):
        self.l=[]

def ret(self):
    self.l.append(randint(10,15))
    return self

IPython的:

In [3]: setattr(MyObject,"ret", ret)

In [4]: MyObject().ret()
Out[4]: <test.MyObject at 0x7f6428e8ccd0>

In [5]: MyObject().ret().l
Out[5]: [15]