[英]Python: can I write a polymorphic swap on mutable objects?
This blog post (currently discussed on Hacker News ) states: 这篇博客文章 (目前在Hacker News上进行了讨论 )指出:
There's a simple "litmus test" for whether a language supports pass-by-reference semantics:
有一种简单的“石蕊试纸”,用于测试语言是否支持按引用传递语义:
Can you write a traditional swap(a,b) method/function in the language?
您可以用该语言编写传统的swap(a,b)方法/函数吗?
A traditional swap method or function takes two arguments and swaps them such that variables passed into the function are changed outside the function.
传统的交换方法或函数需要两个参数并进行交换,以使传递到函数中的变量在函数外部更改。
AFAIK, in Python, a "traditional swap function" on immutable objects is a no-no. AFAIK,在Python中,对不可变对象的“传统交换函数”是禁止的。 But what about mutable objects?
但是可变对象呢? Out of curiosity, I wrote the following tests:
出于好奇,我编写了以下测试:
# Pythonic way to swap variables
(l1, l2) = ([1], [2])
(l1, l2) = (l2, l1)
assert (l1, l2) == ([2], [1])
# This doesn't work inside a function,
# since new bindings are created and discarded
def failed_swap(a, b):
(a, b) = (b, a)
(l1, l2) = ([1], [2])
failed_swap(l1, l2)
assert (l1, l2) == ([1], [2])
# Working swap function (procedure) on lists
def swap_lists(a, b):
aux = a[:]
a[:] = b[:]
b[:] = aux[:]
(l1, l2) = ([1], [2])
swap_lists(l1, l2)
assert (l1, l2) == ([2], [1])
# The same thing on dicts and sets, thanks to duck typing
def swap_dicts_or_sets(a, b):
aux = a.copy()
a.clear()
a.update(b)
b.clear()
b.update(aux)
(s1, s2) = ({1}, {2})
swap_dicts_or_sets(s1, s2)
assert (s1, s2) == ({2}, {1})
(d1, d2) = ({"foo": 1}, {"bar": 2})
swap_dicts_or_sets(d1, d2)
assert (d1, d2) == ({"bar": 2}, {"foo": 1})
So, it seems that I could write some specialized "traditional swaps" on at least some mutable types. 因此,看来我可以至少在某些可变类型上编写一些专门的“传统交换”。
Answer to 1 is something like "Python always uses pass arguments by constant reference to objects ". 对1的回答类似于“ Python始终通过对对象的常量引用来使用传递参数 ”。
Answer to 2 is: no, you cannot do it in a generic way, to find some counter-examples, suppose that you want to swap 2 nodes in a tree: 对2的回答是:不,您不能以通用的方式来找到一些反例,假设您想在树中交换2个节点:
r
/ \
a b
/
c
and say that c
knows its parent is a
; 并说
c
知道它的父母是a
; after you did your "generic swap", c
would still think that the object a
is its parent, but a
would think it has no children and b
consider c
as its child. 完成“通用交换”后,
c
仍会认为对象a
是其父对象,但是a
会认为对象没有子对象, b
则将c
视为其子对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.