go to index

Lists

read time 15 min read
Kaggle Python

Lists

Lists

在Python中,Lists(列表)表示值的有序序列,下面是一个如何构建它们的例子:

python
primes = [2, 3, 5, 7]

我们可以把其他类型的东西放在列表中:

python
planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']

我们甚至可以列一个列表的列表:

python
hands = [
    ['J', 'Q', 'K'],
    ['2', '2', '2'],
    ['6', 'A', 'K'], # (Comma after the last element is optional)
]
# (I could also have written this on one line, but it can get hard to read)
hands = [['J', 'Q', 'K'], ['2', '2', '2'], ['6', 'A', 'K']]

列表可以包含不同类型变量的混合:

python
my_favourite_things = [32, 'raindrops on roses', help]
# (Yes, Python's help function is *definitely* one of my favourite things)

Indexing

您可以访问带有方括号的单个列表元素。

哪颗行星离太阳最近?Python使用从零开始的索引,所以第一个元素的索引为0。

python
planets[0]
plaintext
'Mercury'

下一个离我们最近的行星是什么?

python
planets[1]
plaintext
'Venus'

哪颗行星离太阳最远?

列表末尾的元素可以用负数访问,从-1开始:

python
planets[-1]
plaintext
'Neptune'
python
planets[-2]
plaintext
'Uranus'

Slicing

前三颗行星是什么?我们可以用**slicing(切片)**来回答这个问题:

python
planets[0:3]
plaintext
['Mercury', 'Venus', 'Earth']

planets[0:3] 是我们寻找行星元素的方式,从索引0开始,一直到但不包括索引3。

起始和结束索引都是可选的。如果省略起始下标,它就会被假设为0。所以我可以把上面的表达式重写为

python
planets[:3]
plaintext
['Mercury', 'Venus', 'Earth']

如果我省略了结束索引,它就会被认为是列表的长度。

python
planets[3:]
plaintext
['Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']

例如,上面的表达意思是“给我从指标3开始的所有行星”。

切片时也可以使用负下标:

python
# All the planets except the first and last
planets[1:-1]
plaintext
['Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus']
python
# The last 3 planets
planets[-3:]
plaintext
['Saturn', 'Uranus', 'Neptune']

Changing lists

列表是**“mutable(可变的)”**,这意味着它们可以“适当的”修改。

修改列表的一种方法是给索引或切片表达式赋值。

例如,假设我们想重命名火星:

python
planets[3] = 'Malacandra'
planets
plaintext
['Mercury',
 'Venus',
 'Earth',
 'Malacandra',
 'Jupiter',
 'Saturn',
 'Uranus',
 'Neptune']

嗯,挺拗口的。让我们通过缩短前3个行星的名字来弥补。

python
planets[:3] = ['Mur', 'Vee', 'Ur']
print(planets)
# That was silly. Let's give them back their old names
planets[:4] = ['Mercury', 'Venus', 'Earth', 'Mars',]
plaintext
['Mur', 'Vee', 'Ur', 'Malacandra', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']

List functions

Python提供了几个有用的函数来处理列表。

Len给出了列表的长度:

python
# How many planets are there?
len(planets)
plaintext
8

sorted返回一个排序后的列表:

python
# The planets sorted in alphabetical order
sorted(planets)
plaintext
['Earth', 'Jupiter', 'Mars', 'Mercury', 'Neptune', 'Saturn', 'Uranus', 'Venus']

sum 和你预期的一样:

python
primes = [2, 3, 5, 7]
sum(primes)
plaintext
17

前面我们使用minmax来获取多个参数的最小值或最大值。但我们也可以传入一个列表参数。

python
max(primes)
plaintext
7

Interlude: objects

到目前为止,我已经多次使用“object(对象)”这个术语——你可能已经读到Python中的所有东西都是对象。这是什么意思?

简而言之,objects 随身携带一些东西。你可以使用Python的点语法来访问这些东西。

例如,在Python中,数字带有一个名为imag的关联变量,表示数字的虚部。(除非你在做一些非常奇怪的数学运算,否则你可能永远不需要使用它。)

python
x = 12
# x is a real number, so its imaginary part is 0.
print(x.imag)
# Here's how to make a complex number, in case you've ever been curious:
c = 12 + 3j
print(c.imag)
plaintext
0
3.0

对象携带的东西也可以包括函数。附加到对象上的函数称为方法。(附加到对象上的非函数的东西,如imag,称为属性。)

例如,数字有一个名为bit_length的方法。同样,我们使用点语法访问它:

python
x.bit_length
plaintext
<function int.bit_length()>

要真正调用它,我们需要加上一对括号:

python
x.bit_length()
plaintext
4

顺便说一句,如果你做了练习,你实际上已经调用了方法。在练习笔记q1、q2、q3等中,所有对象都有名为check、hint和solution的方法。

就像我们可以将函数传递给help函数一样(例如help(max)),我们也可以传递方法:

python
help(x.bit_length)
python
Help on built-in function bit_length:

bit_length() method of builtins.int instance
    Number of bits necessary to represent self in binary.
    
    >>> bin(37)
    '0b100101'
    >>> (37).bit_length()
    6

上面的例子完全晦涩难懂。到目前为止,我们所见过的对象类型(数字、函数、布尔值)都没有你可能会用到的属性或方法。

但事实证明,列表有几个你会一直使用的方法。

List methods

list.append 通过在列表末尾添加元素来修改列表:

python
# Pluto is a planet darn it!
planets.append('Pluto')

为什么上面的单元格没有输出?让我们通过调用help(planets.append)来查看文档。

附注:append是所有list类型对象(不仅仅是planets)都包含的方法,所以我们也可以调用help(list.append)。然而,如果我们试图调用help(append), Python将提示不存在名为”append”的变量。“append”名称只存在于列表中——它不像内置函数max或len那样作为独立名称存在。

python
help(planets.append)
python
Help on built-in function append:

append(object, /) method of builtins.list instance
    Append object to the end of the list.

阅读文档可以知道list.Append不返回任何东西。但是如果我们检查planets的值,我们可以看到这个方法调用修改了planets的值:

python
planets
plaintext
['Mercury',
 'Venus',
 'Earth',
 'Mars',
 'Jupiter',
 'Saturn',
 'Uranus',
 'Neptune',
 'Pluto']

list.pop移除并返回列表的最后一个元素:

python
planets.pop()
plaintext
'Pluto'
python
planets
plaintext
['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']

Searching lists

在planets的排列顺序中,Earth落在什么位置?我们可以通过list.index方法获得它的索引。

python
planets.index('Earth')
plaintext
2

它排在第三位(即索引为2 - 0的索引!)。

Pluto的索引是什么呢?

python
planets.index('Pluto')
python
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_19/2263615293.py in <module>
----> 1 planets.index('Pluto')

ValueError: 'Pluto' is not in list

哦,对了……

为了避免这样的意外,我们可以使用in操作符来确定列表是否包含特定的值:

python
# Is Earth a planet?
"Earth" in planets
plaintext
True
python
# Is Calbefraques a planet?
"Calbefraques" in planets
plaintext
False

还有一些更有趣的列表方法我们还没有介绍。如果您想了解附加到特定对象上的所有方法和属性,我们可以对对象本身调用help()。例如,help(planets)将告诉我们所有的list方法:

python
help(planets)
python
Help on list object:

class list(object)
 |  list(iterable=(), /)
 |  
 |  Built-in mutable sequence.
 |  
 |  If no argument is given, the constructor creates a new empty list.
 |  The argument must be an iterable if specified.
 |  
 |  Methods defined here:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __iadd__(self, value, /)
 |      Implement self+=value.
 |  
 |  __imul__(self, value, /)
 |      Implement self*=value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(self, /)
 |      Return a reverse iterator over the list.
 |  
 |  __rmul__(self, value, /)
 |      Return value*self.
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(self, /)
 |      Return the size of the list in memory, in bytes.
 |  
 |  append(self, object, /)
 |      Append object to the end of the list.
 |  
 |  clear(self, /)
 |      Remove all items from list.
 |  
 |  copy(self, /)
 |      Return a shallow copy of the list.
 |  
 |  count(self, value, /)
 |      Return number of occurrences of value.
 |  
 |  extend(self, iterable, /)
 |      Extend list by appending elements from the iterable.
 |  
 |  index(self, value, start=0, stop=9223372036854775807, /)
 |      Return first index of value.
 |      
 |      Raises ValueError if the value is not present.
 |  
 |  insert(self, index, object, /)
 |      Insert object before index.
 |  
 |  pop(self, index=-1, /)
 |      Remove and return item at index (default last).
 |      
 |      Raises IndexError if list is empty or index is out of range.
 |  
 |  remove(self, value, /)
 |      Remove first occurrence of value.
 |      
 |      Raises ValueError if the value is not present.
 |  
 |  reverse(self, /)
 |      Reverse *IN PLACE*.
 |  
 |  sort(self, /, *, key=None, reverse=False)
 |      Stable sort *IN PLACE*.
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None

点击“输出”按钮查看完整的帮助页面。列表有很多方法的名字看起来很奇怪,比如__eq__和__iadd__。现在不要太担心这些。(您可能永远不会直接调用这些方法。但是当我们使用诸如索引或比较运算符之类的语法时,它们会在幕后被调用。)最有趣的方法位于列表的底部(追加、清除、复制等)。

Tuples

元组几乎与列表完全相同。它们只在两个方面有所不同。

1:创建它们的语法使用圆括号而不是方括号

python
t = (1, 2, 3)
python
t = 1, 2, 3 # equivalent to above
t
plaintext
(1, 2, 3)

2:它们不能被修改(它们是不可变的)。

plaintext
t[0] = 100
python
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_19/816329950.py in <module>
----> 1 t[0] = 100

TypeError: 'tuple' object does not support item assignment

元组通常用于具有多个返回值的函数。

例如,float对象的as_integer_ratio()方法以元组的形式返回分子和分母:

python
x = 0.125
x.as_integer_ratio()
plaintext
(1, 8)

这些多个返回值可以单独赋值如下:

python
numerator, denominator = x.as_integer_ratio()
print(numerator / denominator)
plaintext
0.125

最后,我们深入了解了用于交换两个变量的经典愚蠢Python技巧™!

python
a = 1
b = 0
a, b = b, a
print(a, b)
plaintext
0 1

Exercise

Question 1

根据文档字符串完成下面的函数。

python
def select_second(L):
    """Return the second element of the given list. If the list has no second
    element, return None.
    """
    pass
    return L[1] if len(L) >= 2 else None

# Check your answer
q1.check()

Question 2

你正在分析运动队。每个团队的成员存储在一个列表中。教练是名单上的第一个名字,队长是名单上的第二个名字,其他球员在那之后列出。这些列表存储在另一个列表中,该列表从最好的团队开始,一直到最差的团队。完成下面的功能,选择最差队伍的队长。

python
def losing_team_captain(teams):
    """Given a list of teams, where each team is a list of names, return the 2nd player (captain)
    from the last listed team
    """
    return teams[len(teams)-1][1]
    pass

# Check your answer
q2.check()

Question 3

下一个迭代的马里奥赛车将有一个特别令人愤怒的新项目,紫色外壳。当使用时,它会将最后一名赛车手扭曲成第一名,并将第一名赛车手扭曲成最后一名。完成下面的函数来实现紫色外壳的效果。

python
def purple_shell(racers):
    """Given a list of racers, set the first place racer (at the front of the list) to last
    place and vice versa.
    
    >>> r = ["Mario", "Bowser", "Luigi"]
    >>> purple_shell(r)
    >>> r
    ["Luigi", "Bowser", "Mario"]
    """
    pass
    racers[0],racers[-1] = racers[-1],racers[0]
# Check your answer
q3.check()

Question 4

以下列表的长度是多少?用您的预测填入可变长度。(尝试对每个列表进行预测,而不只是对其调用len()。)

python
a = [1, 2, 3]
b = [1, [2, 3]]
c = []
d = [1, 2, 3][1:]

# Put your predictions in the list below. Lengths should contain 4 numbers, the
# first being the length of a, the second being the length of b and so on.
lengths = [3,2,0,2]

# Check your answer
q4.check()

Question 5

我们用列表来记录参加我们聚会的人以及他们到达的顺序。例如,下面的列表代表一个有7位客人的派对,其中Adela第一个出现,Ford最后一个到达:

python
party_attendees = ['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford']

如果一位客人比聚会上至少一半的客人晚到,那么他就被认为是“迟到了”。然而,他们不能是最后一个客人(这太过分了)。在上面的例子中,Mona和Gilbert是唯一迟到的客人。

完成下面的函数,获取聚会参与者和某人的列表,并告诉我们该人是否迟到了。

python
def fashionably_late(arrivals, name):
    """Given an ordered list of arrivals to the party and a name, return whether the guest with that
    name was fashionably late.
    """
    pass
    return arrivals.index(name) >= len(arrivals) / 2 and arrivals.index(name) != len(arrivals) -1 
# Check your answer
q5.check()