Return 方法中的就地修改语句
Return statement in method that modifies in-place
假设我想要一个简单的方法,它采用 list
并通过向其附加 5
来就地修改它。下面是执行此操作的两种方法,但是 ret(l)
returns 而 no_ret(l)
不会。
def ret(l):
l.append(5)
return l
def no_ret(l):
l.append(5)
哪种方法更pythonic?我猜 no_ret()
因为如果该方法用于就地修改,那么就不需要 return 因为我们已经有了对被修改对象的引用。
它们在时间和 space 效率方面的比较如何?
- 就时间而言,我认为
ret(l)
较慢,因为 return 语句会增加额外的开销。
- 对于 space,我相信它们是相同的,因为
ret()
只是 return 一个引用(内存地址),所以没有使用新的内存。
我注意到 Python 提供了就地非 returning 实例方法 sort()
和非就地 returning 静态方法 sorted()
。但是我不能让我的就地方法成为默认 类 的实例方法,比如 list
。
您不应该做的第一件事是用您自己的方法复制现有功能 - 但是,我假设您只是在举一个例子,这不是您计划的实际代码运行.
所有方法都在Pythonreturn一个值。如果一个方法没有 return 语句,它 returns None
.
任何就地修改但不修改的函数return;不应该 return 一个值。这是有道理的,因为这就是 "normal" 就地方法的工作方式。
正确的实施方式是:
def do_something(foo, bar):
foo.do_something_inplace(bar)
return None # or simply, return
空白 return 与 return None
相同,但请记住 - 显式优于隐式。
至于您关于 space 和时间效率的其他问题,这将完全取决于实际进行替换的方法的实现。当您在示例中为内置方法编写代理时,"speed penalty" 可以忽略不计。
在评估 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'
我们可以得出结论,就地方法应该 return 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)
在 IPython 与 %timeit
:
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
not-returning 方法 not 比 C-Python.
中的 returning 更快
编辑评论
您可以使任何方法成为 python 中 class 的实例方法:
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]
假设我想要一个简单的方法,它采用 list
并通过向其附加 5
来就地修改它。下面是执行此操作的两种方法,但是 ret(l)
returns 而 no_ret(l)
不会。
def ret(l):
l.append(5)
return l
def no_ret(l):
l.append(5)
哪种方法更pythonic?我猜 no_ret()
因为如果该方法用于就地修改,那么就不需要 return 因为我们已经有了对被修改对象的引用。
它们在时间和 space 效率方面的比较如何?
- 就时间而言,我认为
ret(l)
较慢,因为 return 语句会增加额外的开销。 - 对于 space,我相信它们是相同的,因为
ret()
只是 return 一个引用(内存地址),所以没有使用新的内存。
我注意到 Python 提供了就地非 returning 实例方法 sort()
和非就地 returning 静态方法 sorted()
。但是我不能让我的就地方法成为默认 类 的实例方法,比如 list
。
您不应该做的第一件事是用您自己的方法复制现有功能 - 但是,我假设您只是在举一个例子,这不是您计划的实际代码运行.
所有方法都在Pythonreturn一个值。如果一个方法没有 return 语句,它 returns None
.
任何就地修改但不修改的函数return;不应该 return 一个值。这是有道理的,因为这就是 "normal" 就地方法的工作方式。
正确的实施方式是:
def do_something(foo, bar):
foo.do_something_inplace(bar)
return None # or simply, return
空白 return 与 return None
相同,但请记住 - 显式优于隐式。
至于您关于 space 和时间效率的其他问题,这将完全取决于实际进行替换的方法的实现。当您在示例中为内置方法编写代理时,"speed penalty" 可以忽略不计。
在评估 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'
我们可以得出结论,就地方法应该 return 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)
在 IPython 与 %timeit
:
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
not-returning 方法 not 比 C-Python.
中的 returning 更快编辑评论
您可以使任何方法成为 python 中 class 的实例方法:
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]