Why was p[:] designed to work differently in these two situations?

后端 未结 6 1171
感动是毒
感动是毒 2021-02-01 12:42
p = [1,2,3]
print(p) # [1, 2, 3]

q=p[:]  # supposed to do a shallow copy
q[0]=11
print(q) #[11, 2, 3] 
print(p) #[1, 2, 3] 
# above confirms that q is not p, and is a d         


        
6条回答
  •  隐瞒了意图╮
    2021-02-01 13:16

    Basically the slice-syntax can be used in 3 different contexts:

    • Accessing, i.e. x = foo[:]
    • Setting, i.e. foo[:] = x
    • Deleting, i.e. del foo[:]

    And in these contexts the values put in the square brackets just select the items. This is designed that the "slice" is used consistently in each of these cases:

    • So x = foo[:] gets all elements in foo and assigns them to x. This is basically a shallow copy.

    • But foo[:] = x will replace all elements in foo with the elements in x.

    • And when deleting del foo[:] will delete all elements in foo.

    However this behavior is customizable as explained by 3.3.7. Emulating container types:

    object.__getitem__(self, key)

    Called to implement evaluation of self[key]. For sequence types, the accepted keys should be integers and slice objects. Note that the special interpretation of negative indexes (if the class wishes to emulate a sequence type) is up to the __getitem__() method. If key is of an inappropriate type, TypeError may be raised; if of a value outside the set of indexes for the sequence (after any special interpretation of negative values), IndexError should be raised. For mapping types, if key is missing (not in the container), KeyError should be raised.

    Note

    for loops expect that an IndexError will be raised for illegal indexes to allow proper detection of the end of the sequence.

    object.__setitem__(self, key, value)

    Called to implement assignment to self[key]. Same note as for __getitem__(). This should only be implemented for mappings if the objects support changes to the values for keys, or if new keys can be added, or for sequences if elements can be replaced. The same exceptions should be raised for improper key values as for the __getitem__() method.

    object.__delitem__(self, key)

    Called to implement deletion of self[key]. Same note as for __getitem__(). This should only be implemented for mappings if the objects support removal of keys, or for sequences if elements can be removed from the sequence. The same exceptions should be raised for improper key values as for the __getitem__() method.

    (Emphasis mine)

    So in theory any container type could implement this however it wants. However many container types follow the list-implementation.

提交回复
热议问题