赋值运算符左侧/右侧的不同切片行为 [英] Different slicing behaviors on left/right hand side of assignment operator

查看:82
本文介绍了赋值运算符左侧/右侧的不同切片行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为来自C ++背景的Python新手,Python(3.4.x)中的切片运算符对我来说似乎很荒谬.我只是不了解特殊规则"背后的设计理念.让我解释一下为什么我说这是特殊"的.

As a Python newbie coming from the C++ background, the slicing operator in Python (3.4.x) looks ridiculous to me. I just don't get the design philosophy behind the "special rule". Let me explain why I say it's "special".

一方面,根据堆栈溢出的答案在此处切片运算符创建列表的一部分(深)副本或列表的一部分,即新列表.该链接可能较旧(早于python 3.4.x),但是我只是通过以下简单的python 3.4.2实验确认了该行为:

On the one hand, according to the Stack Overflow answer here, the slicing operator creates a (deep) copy of a list or part of the list, i.e. a new list. The link may be old (earlier than python 3.4.x), but I just confirmed the behavior with the following simple experiment with python 3.4.2:

words = ['cat', 'window', 'defenestrate']
newList = words[:] # new objects are created; a.k.a. deep copy
newList[0] = 'dog'

print(words) # ['cat' ...
print(newList) # ['dog' ...

另一方面,根据官方文档此处:

On the other hand, according to the official documentation here:

Assignment to slices is also possible, and this can even change the size of the list or clear it entirely:
>>>

>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> # replace some values
>>> letters[2:5] = ['C', 'D', 'E']
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> # now remove them
>>> letters[2:5] = []
>>> letters
['a', 'b', 'f', 'g']
>>> # clear the list by replacing all the elements with an empty list
>>> letters[:] = []
>>> letters 
[]

很显然,切片运算符[:]不在此处进行深层复制.

Clearly, the slicing operator [:] does not do a deep copy here.

根据观察结果,似乎表明切片运算符相对于赋值运算符位于左侧/右侧时会产生不同的行为.我不知道任何一种操作员都可以产生类似行为的语言.毕竟,运算符是一个函数,只是语法上特殊的函数,并且该函数的行为应是自包含的,完全由其所有输入确定.

From the observation it seems to suggest that the slicing operator produces different behavior when it's on left/right side with respect to the assignment operator. I do not know any language in which an operator could produce similar behavior. After all, an operator is a function, just a syntactically special function, and a function's behavior should be self-contained, purely determined by all of its inputs.

那么在Python设计哲学中有什么可以证明这一特殊规则"的合理性呢?

So what can justify this "special rule" in Python design philosophy?

P.S.如果我的结论不正确,那么实际上只有两种可能性:

P.S. If my conclusion is not correct, there are really only two possibilities:

1,Python的切片运算符"实际上不是运算符,因此我的假设不成立---那是什么(切片运算符" [:])?

1, Python's slicing 'operator' is actually not an operator, so my assumption does not hold --- then what is it (the 'slicing operator' [:])?

2,行为差异是由于未观察到某些潜在因素引起的.切片操作员相对于分配操作员的位置(左侧/右侧)与观察到的不同行为意外地并存.他们没有因果关系---那么导致行为差异的潜在因素是什么?

2, The difference in behavior is caused by some latent factor not observed. The slicing operator's location (left/right hand side) with respect to the assignment operator accidentally co-exists with the observation of different behavior. They do not have causality relationship --- then what is the latent factor that causes the difference in behavior?

推荐答案

对于魔术" 方法,最好将Python运算符视为语法糖.例如,x + y被评估为x.__add__(y).用相同的方式:

Python operators are best considered as syntactic sugar for "magic" methods; for example, x + y is evaluated as x.__add__(y). In the same way that:

  • foo = bar.baz变为foo = bar.__getattr__(baz);而
  • bar.baz = foo变为bar.__setattr__(baz, foo);
  • foo = bar.baz becomes foo = bar.__getattr__(baz); whereas
  • bar.baz = foo becomes bar.__setattr__(baz, foo);

Python 切片运算符" * a[b]被评估为:

the Python "slicing operator" * a[b] is evaluated as either:

  • a.__getitem__(b);或
  • a.__setitem__(b, ...);
  • a.__getitem__(b); or
  • a.__setitem__(b, ...);

取决于它在作业的哪一边;两者不太相同相同(另请参见赋值如何与python列表切片一起使用) .因此写在"longhand" 中,

depending on which side of the assignment it's on; the two aren't quite the same (see also How assignment works with python list slice). Written out in "longhand", therefore:

>>> x = [1, 2, 3]
>>> x.__getitem__(slice(None))  # ... = x[:]
[1, 2, 3]
>>> x.__setitem__(slice(None), (4, 5, 6))  # x[:] = ...
>>> x
[4, 5, 6]

数据模型文档详细说明了这些方法(例如, __getitem__ ),您可以阅读 slice 上的文档也是如此.

The data model documentation explains these methods in more detail (e.g. __getitem__), and you can read the docs on slice, too.

请注意,切片是一个浅拷贝,而不是一个深拷贝,如下所示:

Note that the slice is a shallow copy, not a deep one, as the following demonstrates:

>>> foo = [[], []]
>>> bar = foo[:]
>>> bar is foo
False  # outer list is new object
>>> bar[0] is foo[0]
True  # inner lists are same objects
>>> bar[0].append(1)
>>> foo
[[1], []]


*嗯,不是严格地 一个 operator .


* Well, not strictly an operator.

这篇关于赋值运算符左侧/右侧的不同切片行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆