Python学习第3节:列表(list)、元组(tuple)、字典(dict)和集合(set)

序列索引(正负数都索引都有)

str="C语言中文网"

print(str[0],"==",str[-6])

print(str[5],"==",str[-1])

结果:

C == C

网 == 网

list列表

语法:所有元素都放在一对中括号[ ]里面,相邻元素之间用逗号,分隔;列表可以存储整数、小数、字符串、列表、元组等任何类型的数据

创建列表[] 或者list()转换

方式1:直接定义

emptylist = [ ]

list1= ["http://c.biancheng.net/python/", 1, [2,3,4] , 3.0]

方式2:通过转换成list格式

#将字符串转换成列表

list1 = list("hello")

print(list1)

#将元组转换成列表

tuple1 = ('Python', 'Java', 'C++', 'JavaScript')

list2 = list(tuple1)

print(list2)

#将字典转换成列表

dict1 = {'a':100, 'b':42, 'c':9}

list3 = list(dict1)

print(list3)

#将区间转换成列表

range1 = range(1, 6)

list4 = list(range1)

print(list4)

#还可以创建空列表

print(list())

以上运行结果:

['h', 'e', 'l', 'l', 'o']

['Python', 'Java', 'C++', 'JavaScript']

['a', 'b', 'c']

[1, 2, 3, 4, 5]

[]

访问列表元素 listname[i] /[start : end : step]

语法:

listname[i]

listname[start : end : step] #start 表示起始索引,end 表示结束索引,step 表示步长。

添加元素 +,append,extend,insert

1. 直接用+连接列表 (效率不高)

使用+会生成一个新的列表,原有的列表不会被改变。
+更多的是用来拼接列表,而且执行效率并不高

language = ["Python", "C++", "Java"]
birthday = [1991, 1998, 1995]
info = language + birthday

print("info =", info)

运行结果:info = ['Python', 'C++', 'Java', 1991, 1998, 1995]

2. append和extend

listname.append(obj)

listname.extend(obj)

listname.insert(index , obj)

extend() 和 append() 的不同之处在于:extend() 不会把列表或者元祖视为一个整体,而是把它们包含的元素逐个添加到列表中。

区别:

l = ['Python', 'C++', 'Java']

l.append(['Ruby', 'SQL']) #输出:['Python', 'C++', 'Java', ['Ruby', 'SQL']]

l.extend(['Ruby', 'SQL']) #输出:['Python', 'C++', 'Java', 'Ruby', 'SQL']

3. insert()

append() 和 extend() 方法只能在列表末尾插入元素,如果希望在列表中间某个位置插入元素,那么可以使用 insert() 方法。

l = ['Python', 'C++', 'Java']

l.insert(1, 'C')

print(l)

结果:

['Python', 'C', 'C++', 'Java']

删除列表del(少用)

Python 自带的垃圾回收机制会自动销毁无用的列表,即使开发者不手动删除,Python 也会自动将其回收

语法:del listname

intlist = [1, 45, 8, 34]

print(intlist)

del intlist

删除元素 del[index]/[start : end]/pop()/clear()

del删除指定单个或连续索引元素:

1. del listname[index] 

2. del listname[start : end]   #start 表示起始索引,end 表示结束索引。del 会删除从索引 start 到 end 之间的元素,不包括 end 位置的元素

lang = ["Python", "C++", "Java", "PHP", "Ruby", "MATLAB"]

del lang[1: 4]
print(lang)

lang.extend(["SQL", "C#", "Go"])
del lang[-5: -2]
print(lang)

运行结果:
['Python', 'Ruby', 'MATLAB']
['Python', 'C#', 'Go']

pop删除指定索引元素:

1. listname.pop(index)

如果不写 index 参数,默认会删除列表中的最后一个元素,类似于数据结构中的“出栈”操作

nums = [40, 36, 89, 2, 36, 100, 7]
nums.pop(3)
print(nums)

运行结果:
[40, 36, 89, 36, 100, 7]

remove删除指定值元素

remove() 方法只会删除第一个和指定值相同的元素,而且必须保证该元素是存在的,否则会引发 ValueError 错误

nums = [40, 36, 89, 2, 36, 100, 7]
#第一次删除36
nums.remove(36)
print(nums)
#第二次删除36
nums.remove(36)

运行结果:

[40, 89, 2, 36, 100, 7]
[40, 89, 2, 100, 7]

clear删除所有元素

url = list("http://c.biancheng.net/python/")
url.clear()
print(url)

运行结果:

[]

修改元素的值 =

1. 修改单个值,直接赋值即可:

nums = [40, 36, 89, 2, 36, 100, 7]
nums[2] = -26  #使用正数索引
nums[-3] = -66.2  #使用负数索引
print(nums)

运行结果:

[40, 36, -26, 2, -66.2, 100, 7]

2. 修改一组元素赋值,如果不指定步长(step 参数),Python 就不要求新赋值的元素个数与原来的元素个数相同;

nums = [40, 36, 89, 2, 36, 100, 7]

#修改第 1~4 个元素的值(不包括第4个元素)
nums[1: 4] = [45.25, -77, -52.5]
print(nums)

运行结果:
[40, 45.25, -77, -52.5, 36, 100, 7]

3. 修改空的切片,相当于插入一组新的元素

nums = [40, 36, 89, 2, 36, 100, 7]
#在4个位置插入元素
nums[4: 4] = [-77, -52.5, 999]
print(nums)

运行结果:
[40, 36, 89, 2, -77, -52.5, 999, 36, 100, 7]

4. 如果使用字符串赋值,Python 会自动把字符串转换成序列,其中的每个字符都是一个元素

s = list("Hello")
s[2:4] = "XYZ"
print(s)

运行结果:
['H', 'e', 'X', 'Y', 'Z', 'o']

5. 使用切片语法时也可以指定步长(step 参数),但这个时候就要求所赋值的新元素的个数与原有元素的个数相同(感觉没啥用,无聊的功能)

nums = [40, 36, 89, 2, 36, 100, 7]
#步长为2,为第1、3、5个元素赋值
nums[1: 6: 2] = [0.025, -99, 20.5]
print(nums)

运行结果:
[40, 0.025, 89, -99, 36, 20.5, 7]

统计元素索引/次数 index()/count()

1. index()查找元素在列表中的索引地址

语法:listname.index(obj, start, end)   #obj 表示要查找的元素,start 表示起始位置,end 表示结束位置,,

  • start 和 end 可以都不写,此时会检索整个列表;
  • 如果只写 start 不写 end,那么表示检索从 start 到末尾的元素;
  • 如果 start 和 end 都写,那么表示检索 start 和 end 之间的元素。
nums = [40, 36, 89, 2, 36, 100, 7, -20.5, -999]
#检索列表中的所有元素
print( nums.index(2) )
#检索3~7之间的元素
print( nums.index(100, 3, 7) )
#检索4之后的元素
print( nums.index(7, 4) )
#检索一个不存在的元素
print( nums.index(55) )

运行结果:

3
5
6
Traceback (most recent call last):
    File "C:\Users\mozhiyan\Desktop\demo.py", line 9, in <module>
        print( nums.index(55) )
ValueError: 55 is not in list

2. count()统计某个元素出现的次数

语法:listname.count(obj)

nums = [40, 36, 89, 2, 36, 100, 7, -20.5, 36]
#统计元素出现的次数
print("36出现了%d次" % nums.count(36))
#判断一个元素是否存在
if nums.count(100):
    print("列表中存在100这个元素")
else:
    print("列表中不存在100这个元素")

运行结果:

36出现了3次
列表中存在100这个元素

简单初始化数据列表range()

for value in range(1,5):
    print(value)

输出结果为:

1
2
3
4

另外需要指明的是,range() 函数的返回值并不直接是列表类型(list),例如:

>>> type([1,2,3,4,5])
<class 'list'>
>>> type(range(1,6))
<class 'range'>

可以看到,range() 函数的返回值类型为 range,而不是 list。而如果想要得到 range() 函数创建的数字列表,还需要借助 list() 函数,比如:

>>> list(range(1,6))
[1, 2, 3, 4, 5]

在使用 range() 函数时,还可以指定步长。例如,下面的代码打印 1~10 内的偶数:

  1. even_numbers = list(range(2,11,2))
  2. print(even_numbers)

输出如下:

[2, 4, 6, 8, 10]

案例:使用list实现队列和栈

队列:先进先出

栈:后进先出

实现队列:

#定义一个空列表,当做队列
queue = []
#向列表中插入元素
queue.insert(0,1)
queue.insert(0,2)
queue.insert(0,"hello")
print(queue)
print("取一个元素:",queue.pop())
print("取一个元素:",queue.pop())
print("取一个元素:",queue.pop())

运行结果为:

['hello', 2, 1]
取一个元素: 1
取一个元素: 2
取一个元素: hello

实现栈:

#定义一个空 list 当做栈
stack = []
stack.append(1)
stack.append(2)
stack.append("hello")
print(stack)
print("取一个元素:",stack.pop())
print("取一个元素:",stack.pop())
print("取一个元素:",stack.pop())

[1, 2, 'hello']
取一个元素: hello
取一个元素: 2
取一个元素: 1

前面使用 list 实现队列的例子中,插入数据的部分是通过 insert() 方法实现的,这种方法效率并不高,因为每次从列表的开头插入一个数据,列表中所有元素都得向后移动一个位置。

import collections
queueAndStack = collections.deque()
queueAndStack.append(1)
queueAndStack.append(2)
queueAndStack.append("hello")
print(list(queueAndStack))

#实现队列功能,从队列中取一个元素,根据先进先出原则,这里应输出 1
print(queueAndStack.popleft())
#实现栈功能,从栈里取一个元素,根据后进先出原则,这里应输出 hello
print(queueAndStack.pop())
#再次打印列表
print(list(queueAndStack))

输出结果为:

[1, 2, 'hello']
1
hello
[2]

tuple元组

tuple和list的区别

元组和列表(list)的不同之处在于:

  • 列表的元素是可以更改的,包括修改元素值,删除和插入元素,所以列表是可变序列;
  • 而元组一旦被创建,它的元素就不可更改了,所以元组是不可变序列

创建tuple ()或tuple()转换

元组的所有元素都放在一对小括号( )中,相邻元素之间用逗号,分隔

方式1:使用()直接赋值

course = ("Python教程", "http://c.biancheng.net/python/")

  1. num = (7, 14, 21, 28, 35)

小括号不是必须的,只要将各元素用逗号隔开,Python 就会将其视为元组

  1. course = "Python教程", "http://c.biancheng.net/python/"

运行结果为:('Python教程', 'http://c.biancheng.net/python/')

当创建的元组中只有一个字符串类型的元素时,该元素后面必须要加一个逗号,,否则 Python 解释器会将它视为字符串

  1. a =("http://c.biancheng.net/cplus/",)

方式2:使用tuple()函数创建元组

#将字符串转换成元组
tup1 = tuple("hello")
print(tup1)

#将列表转换成元组
list1 = ['Python', 'Java', 'C++', 'JavaScript']
tup2 = tuple(list1)
print(tup2)

#将字典转换成元组
dict1 = {'a':100, 'b':42, 'c':9}
tup3 = tuple(dict1)
print(tup3)

#将区间转换成元组
range1 = range(1, 6)
tup4 = tuple(range1)
print(tup4)

#创建空元组
print(tuple())

访问元组元素 tuplename[i]/[start : end : step]

和列表一样,我们可以使用索引(Index)访问元组中的某个元素(得到的是一个元素的值),也可以使用切片访问元组中的一组元素(得到的是一个新的子元组)。

使用索引访问元组元素的格式为:

tuplename[i]

其中,tuplename 表示元组名字,i 表示索引值。元组的索引可以是正数,也可以是负数。

使用切片访问元组元素的格式为:

tuplename[start : end : step]

其中,start 表示起始索引,end 表示结束索引,step 表示步长。

url = tuple("http://c.biancheng.net/shell/")

#使用索引访问元组中的某个元素
print(url[3]) #使用正数索引
print(url[-4]) #使用负数索引

#使用切片访问元组中的一组元素
print(url[9: 18]) #使用正数切片
print(url[9: 18: 3]) #指定步长
print(url[-6: -1]) #使用负数切片

运行结果:

p
e
('b', 'i', 'a', 'n', 'c', 'h', 'e', 'n', 'g')
('b', 'n', 'e')
('s', 'h', 'e', 'l', 'l')

修改元组 =和+(都是生成新的tuple)

前面我们已经说过,元组是不可变序列,元组中的元素不能被修改,所以我们只能创建一个新的元组去替代旧的元组。
例如,对元组变量进行重新赋值:

tup = (100, 0.5, -36, 73)
print(tup)
#对元组进行重新赋值
tup = ('Shell脚本',"http://c.biancheng.net/shell/")
print(tup)

运行结果为:

(100, 0.5, -36, 73)
('Shell脚本', 'http://c.biancheng.net/shell/')
另外,还可以通过连接多个元组(使用+可以拼接元组)的方式向元组中添加新元素,例如:

tup1 = (100, 0.5, -36, 73)
tup2 = (3+12j, -54.6, 99)
print(tup1+tup2)
print(tup1)
print(tup2)

运行结果为:

(100, 0.5, -36, 73, (3+12j), -54.6, 99)
(100, 0.5, -36, 73)
((3+12j), -54.6, 99)

删除元组 del

当创建的元组不再使用时,可以通过 del 关键字将其删除,例如:

tup = ('Java教程',"http://c.biancheng.net/java/")
print(tup)
del tup
print(tup)

运行结果为:

('Java教程', 'http://c.biancheng.net/java/')
Traceback (most recent call last):
    File "C:\Users\mozhiyan\Desktop\demo.py", line 4, in <module>
        print(tup)
NameError: name 'tup' is not defined

Python 自带垃圾回收功能,会自动销毁不用的元组,所以一般不需要通过 del 来手动删除。

dict字典

创建字典

创建字典的方式有很多,下面一一做介绍。

1) 使用 { } 创建字典

由于字典中每个元素都包含两部分,分别是键(key)和值(value),因此在创建字典时,键和值之间使用冒号:分隔,相邻元素之间使用逗号,分隔,所有元素放在大括号{ }中。

使用{ }创建字典的语法格式如下:

dictname = {'key':'value1', 'key2':'value2', ..., 'keyn':valuen}

其中 dictname 表示字典变量名,keyn : valuen 表示各个元素的键值对。需要注意的是,同一字典中的各个键必须唯一,不能重复。

如下代码示范了使用花括号语法创建字典:

#使用字符串作为key
scores = {'数学': 95, '英语': 92, '语文': 84}
print(scores)

#使用元组和数字作为key
dict1 = {(20, 30): 'great', 30: [1,2,3]}
print(dict1)

#创建空元组
dict2 = {}
print(dict2)

运行结果为:

{'数学': 95, '英语': 92, '语文': 84}
{(20, 30): 'great', 30: [1, 2, 3]}
{}

可以看到,字典的键可以是整数、字符串或者元组,只要符合唯一和不可变的特性就行;字典的值可以是 Python 支持的任意数据类型。

2) 通过 fromkeys() 方法创建字典

Python 中,还可以使用 dict 字典类型提供的 fromkeys() 方法创建带有默认值的字典,具体格式为:

dictname = dict.fromkeys(list,value=None)其中,list 参数表示字典中所有键的列表(list);value 参数表示默认值,如果不写,则为空值 None。
请看下面的例子:

knowledge = ['语文', '数学', '英语']
scores = dict.fromkeys(knowledge, 60)
print(scores)

运行结果为:

{'语文': 60, '英语': 60, '数学': 60}

可以看到,knowledge 列表中的元素全部作为了 scores 字典的键,而各个键对应的值都是 60。这种创建方式通常用于初始化字典,设置 value 的默认值。

3) 通过 dict() 映射函数创建字典

通过 dict() 函数创建字典的写法有多种,表 2 罗列出了常用的几种方式,它们创建的都是同一个字典 a。

表 2 dict() 函数创建字典
创建格式注意事项
a = dict(str1=value1, str2=value2, str3=value3)
a = dict(str1='tom', str2="mary", str3=3)
print(a)
结果:{'str1': 'tom', 'str2': 'mary', 'str3': 3}
#方式1
demo1 = [('two',2), ('one',1), ('three',3)]
#方式2
demo2 = [['two',2], ['one',1], ['three',3]]
#方式3
demo3 = (('two',2), ('one',1), ('three',3))
#方式4
demo4 = (['two',2], ['one',1], ['three',3])
print(dict(demo1))
print(dict(demo2))
print(dict(demo3))
print(dict(demo4))

向 dict() 函数传入列表或元组,而它们中的元素又各自是包含 2 个元素的列表或元组,其中第一个元素作为键,第二个元素作为值。

结果:

{'two': 2, 'one': 1, 'three': 3}
{'two': 2, 'one': 1, 'three': 3}
{'two': 2, 'one': 1, 'three': 3}
{'two': 2, 'one': 1, 'three': 3}

keys = ['one', 'two', 'three'] #还可以是字符串或元组
values = [1, 2, 3] #还可以是字符串或元组
a = dict( zip(keys, values) )
通过应用 dict() 函数和 zip() 函数,可将前两个列表转换为对应的字典。

注意,无论采用以上哪种方式创建字典,字典中各元素的键都只能是字符串、元组或数字,不能是列表。列表是可变的,不能作为键。如果不为 dict() 函数传入任何参数,则代表创建一个空的字典,例如:


# 创建空的字典
d = dict()
print(d)

运行结果为:

{}

访问字典 dictname[key]/get()

列表和元组是通过下标来访问元素的,而字典不同,它通过键来访问对应的值。因为字典中的元素是无序的,每个元素的位置都不固定,所以字典也不能像列表和元组那样,采用切片的方式一次性访问多个元素。

Python 访问字典元素的具体格式为:

dictname[key]

其中,dictname 表示字典变量的名字,key 表示键名。注意,键必须是存在的,否则会抛出异常。
请看下面的例子:

tup = (['two',26], ['one',88], ['three',100], ['four',-59])
dic = dict(tup)
print(dic['one']) #键存在
print(dic['five']) #键不存在

运行结果:

88
Traceback (most recent call last):
    File "C:\Users\mozhiyan\Desktop\demo.py", line 4, in <module>
        print(dic['five'])  #键不存在
KeyError: 'five'


除了上面这种方式外,Python 更推荐使用 dict 类型提供的 get() 方法来获取指定键对应的值。当指定的键不存在时,get() 方法不会抛出异常。
get() 方法的语法格式为:

dictname.get(key[,default])

其中,dictname 表示字典变量的名字;key 表示指定的键;default 用于指定要查询的键不存在时,此方法返回的默认值,如果不手动指定,会返回 None。

get() 使用示例:

  1. a = dict(two=0.65, one=88, three=100, four=-59)
  2. print( a.get('one') )

运行结果:

88


注意,当键不存在时,get() 返回空值 None,如果想明确地提示用户该键不存在,那么可以手动设置 get() 的第二个参数,例如:

  1. a = dict(two=0.65, one=88, three=100, four=-59)
  2. print( a.get('five', '该键不存在') )

运行结果:

该键不存在

删除字典 del

和删除列表、元组一样,手动删除字典也可以使用 del 关键字,例如:

  1. a = dict(two=0.65, one=88, three=100, four=-59)
  2. print(a)
  3. del a
  4. print(a)

运行结果:

{'two': 0.65, 'one': 88, 'three': 100, 'four': -59}
Traceback (most recent call last):
    File "C:\Users\mozhiyan\Desktop\demo.py", line 4, in <module>
        print(a)
NameError: name 'a' is not defined

Python 自带垃圾回收功能,会自动销毁不用的字典,所以一般不需要通过 del 来手动删除。

添加键值对 d[key]=value

为字典添加新的键值对很简单,直接给不存在的 key 赋值即可,具体语法格式如下:

dictname[key] = value

对各个部分的说明:

  • dictname 表示字典名称。
  • key 表示新的键。
  • value 表示新的值,只要是 Python 支持的数据类型都可以。

下面代码演示了在现有字典基础上添加新元素的过程:

a = {'数学':95}
print(a)
#添加新键值对
a['语文'] = 89
print(a)
#再次添加新键值对
a['英语'] = 90
print(a)

运行结果:

{'数学': 95}
{'数学': 95, '语文': 89}
{'数学': 95, '语文': 89, '英语': 90}

修改键值对 d[key]=value

Python 字典中键(key)的名字不能被修改,我们只能修改值(value)。

字典中各元素的键必须是唯一的,因此,如果新添加元素的键与已存在元素的键相同,那么键所对应的值就会被新的值替换掉,以此达到修改元素值的目的。请看下面的代码:

a = {'数学': 95, '语文': 89, '英语': 90}
print(a)
a['语文'] = 100
print(a)

运行结果:

{'数学': 95, '语文': 89, '英语': 90}
{'数学': 95, '语文': 100, '英语': 90}

可以看到,字典中没有再添加一个{'语文':100}键值对,而是对原有键值对{'语文': 89}中的 value 做了修改。

删除键值对 del d[key]

如果要删除字典中的键值对,还是可以使用 del 语句。例如:

# 使用del语句删除键值对
a = {'数学': 95, '语文': 89, '英语': 90}
del a['语文']
del a['数学']
print(a)

运行结果为:

{'英语': 90}

判断是否存在指定键值对 in

如果要判断字典中是否存在指定键值对,首先应判断字典中是否有对应的键。判断字典是否包含指定键值对的键,可以使用 in 或 not in 运算符。

需要指出的是,对于 dict 而言,in 或 not in 运算符都是基于 key 来判断的。例如如下代码:

a = {'数学': 95, '语文': 89, '英语': 90}
# 判断 a 中是否包含名为'数学'的key
print('数学' in a) # True
# 判断 a 是否包含名为'物理'的key
print('物理' in a) # False

运行结果为:

True
False

通过 in(或 not in)运算符,我们可以很轻易地判断出现有字典中是否包含某个键,如果存在,由于通过键可以很轻易的获取对应的值,因此很容易就能判断出字典中是否有指定的键值对。

字典其他函数

>>> dir(dict)
['clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

这些方法中,fromkeys() 和 get() 的用法已在《Python字典》中进行了介绍,这里不再赘述,本节只给大家介绍剩下的方法。

keys()、values() 和 items() 方法

将这三个方法放在一起介绍,是因为它们都用来获取字典中的特定数据:

  • keys() 方法用于返回字典中的所有键(key);
  • values() 方法用于返回字典中所有键对应的值(value);
  • items() 用于返回字典中所有的键值对(key-value)。

请看下面的例子:

scores = {'数学': 95, '语文': 89, '英语': 90}
print(scores.keys())
print(scores.values())
print(scores.items())

运行结果:

dict_keys(['数学', '语文', '英语'])
dict_values([95, 89, 90])
dict_items([('数学', 95), ('语文', 89), ('英语', 90)])

可以发现,keys()、values() 和 items() 返回值的类型分别为 dict_keys、dict_values 和 dict_items。需要注意的是,在 Python 2.x 中,上面三个方法的返回值都是列表(list)类型。但在 Python 3.x 中,它们的返回值并不是我们常见的列表或者元组类型,因为 Python 3.x 不希望用户直接操作这几个方法的返回值。
在 Python 3.x 中如果想使用这三个方法返回的数据,一般有下面两种方案:
1) 使用 list() 函数,将它们返回的数据转换成列表,例如:

a = {'数学': 95, '语文': 89, '英语': 90}
b = list(a.keys())
print(b)

运行结果为:

['数学', '语文', '英语']
2) 使用 for in 循环遍历它们的返回值,例如:

a = {'数学': 95, '语文': 89, '英语': 90}
for k in a.keys():
print(k,end=' ')
print("\n---------------")
for v in a.values():
print(v,end=' ')
print("\n---------------")
for k,v in a.items():
print("key:",k," value:",v)

运行结果为:

数学 语文 英语
---------------
95 89 90
---------------
key: 数学  value: 95
key: 语文  value: 89
key: 英语  value: 90

copy() 方法

copy() 方法返回一个字典的拷贝,也即返回一个具有相同键值对的新字典,例如:

  1. a = {'one': 1, 'two': 2, 'three': [1,2,3]}
  2. b = a.copy()
  3. print(b)

运行结果为:

{'one': 1, 'two': 2, 'three': [1, 2, 3]}

可以看到,copy() 方法将字典 a 的数据全部拷贝给了字典 b。

注意,copy() 方法所遵循的拷贝原理,既有深拷贝,也有浅拷贝。拿拷贝字典 a 为例,copy() 方法只会对最表层的键值对进行深拷贝,也就是说,它会再申请一块内存用来存放 {'one': 1, 'two': 2, 'three': []};而对于某些列表类型的值来说,此方法对其做的是浅拷贝,也就是说,b 中的 [1,2,3] 的值不是自己独有,而是和 a 共有。
请看下面的例子:

a = {'one': 1, 'two': 2, 'three': [1,2,3]}
b = a.copy()
#向 a 中添加新键值对,由于b已经提前将 a 所有键值对都深拷贝过来,因此 a 添加新键值对,不会影响 b。
a['four']=100
print(a)
print(b)
#由于 b 和 a 共享[1,2,3](浅拷贝),因此移除 a 中列表中的元素,也会影响 b。
a['three'].remove(1)
print(a)
print(b)

运行结果为:

{'one': 1, 'two': 2, 'three': [1, 2, 3], 'four': 100}
{'one': 1, 'two': 2, 'three': [1, 2, 3]}
{'one': 1, 'two': 2, 'three': [2, 3], 'four': 100}
{'one': 1, 'two': 2, 'three': [2, 3]}

从运行结果不难看出,对 a 增加新键值对,b 不变;而修改 a 某键值对中列表内的元素,b也会相应改变。

update() 方法

update() 方法可以使用一个字典所包含的键值对来更新己有的字典。

在执行 update() 方法时,如果被更新的字典中己包含对应的键值对,那么原 value 会被覆盖;如果被更新的字典中不包含对应的键值对,则该键值对被添加进去。

请看下面的代码:

  1. a = {'one': 1, 'two': 2, 'three': 3}
  2. a.update({'one':4.5, 'four': 9.3})
  3. print(a)

运行结果为:

{'one': 4.5, 'two': 2, 'three': 3, 'four': 9.3}

从运行结果可以看出,由于被更新的字典中已包含 key 为“one”的键值对,因此更新时该键值对的 value 将被改写;而被更新的字典中不包含 key 为“four”的键值对,所以更新时会为原字典增加一个新的键值对。

pop() 和 popitem() 方法

pop() 和 popitem() 都用来删除字典中的键值对,不同的是,pop() 用来删除指定的键值对,而 popitem() 用来随机删除一个键值对,它们的语法格式如下:

dictname.pop(key)
dictname.popitem()

其中,dictname 表示字典名称,key 表示键。
下面的代码演示了两个函数的用法:

  1. a = {'数学': 95, '语文': 89, '英语': 90, '化学': 83, '生物': 98, '物理': 89}
  2. print(a)
  3. a.pop('化学')
  4. print(a)
  5. a.popitem()
  6. print(a)

运行结果:

{'数学': 95, '语文': 89, '英语': 90, '化学': 83, '生物': 98, '物理': 89}
{'数学': 95, '语文': 89, '英语': 90, '生物': 98, '物理': 89}
{'数学': 95, '语文': 89, '英语': 90, '生物': 98}

对 popitem() 的说明

其实,说 popitem() 随机删除字典中的一个键值对是不准确的,虽然字典是一种无须的列表,但键值对在底层也是有存储顺序的,popitem() 总是弹出底层中的最后一个 key-value,这和列表的 pop() 方法类似,都实现了数据结构中“出栈”的操作。

setdefault() 方法

setdefault() 方法用来返回某个 key 对应的 value,其语法格式如下:

dictname.setdefault(key, defaultvalue)

说明,dictname 表示字典名称,key 表示键,defaultvalue 表示默认值(可以不写,不写的话是 None)。

当指定的 key 不存在时,setdefault() 会先为这个不存在的 key 设置一个默认的 defaultvalue,然后再返回 defaultvalue。

也就是说,setdefault() 方法总能返回指定 key 对应的 value:

  • 如果该 key 存在,那么直接返回该 key 对应的 value;
  • 如果该 key 不存在,那么先为该 key 设置默认的 defaultvalue,然后再返回该 key 对应的 defaultvalue。


请看下面的代码:

 
  1. a = {'数学': 95, '语文': 89, '英语': 90}
  2. print(a)
  3. #key不存在,指定默认值
  4. a.setdefault('物理', 94)
  5. print(a)
  6. #key不存在,不指定默认值
  7. a.setdefault('化学')
  8. print(a)
  9. #key存在,指定默认值
  10. a.setdefault('数学', 100)
  11. print(a)

运行结果为:

{'数学': 95, '语文': 89, '英语': 90}
{'数学': 95, '语文': 89, '英语': 90, '物理': 94}
{'数学': 95, '语文': 89, '英语': 90, '物理': 94, '化学': None}
{'数学': 95, '语文': 89, '英语': 90, '物理': 94, '化学': None}

字典格式化字符串 %

我们介绍了如何使用 print() 格式化输出各种类型的数据。我们知道,如果格式化字符串的模板中包含了多个转换说明符,后面就得按照顺序给出多个对应的变量;当字符串模板中只包含少量转换说明符时,这种写法还是比较合适的,但如果字符串模板中包含大量转换说明符,这种按顺序提供变量的方式就有些麻烦了。

这时,就可以使用字典对字符串进行格式化输出,具体方法是:在字符串模板中按 key 指定变量,然后通过字典为字符串模板中的 key 设置值。

请看下面的代码:

# 字符串模板中使用key
temp = '教程是:%(name)s, 价格是:%(price).2f, 网址是:%(url)s'
course = {'name':'Python教程', 'price': 9.9, 'url': 'http://c.biancheng.net/python/'}
# 使用字典为字符串模板中的key传入值
print(temp % course)
course = {'name':'C++教程', 'price':15.6, 'url': 'http://c.biancheng.net/cplus/'}
# 使用字典为字符串模板中的key传入值
print(temp % course)

运行上面程序,可以看到如下输出结果:

教程是:Python教程, 价格是:9.90, 网址是:http://c.biancheng.net/python/
教程是:C++教程, 价格是:15.60, 网址是:http://c.biancheng.net/cplus/

set集合

1. 用来保存不重复的元素,即集合中的元素都是唯一的,互不相同。

2. set 类型集合可以做添加、删除元素的操作

3。 从形式上看,和字典类似,Python 集合会将所有元素放在一对大括号 {} 中,相邻元素之间用“,”分隔,如下所示:

{element1,element2,...,elementn}

从内容上看,同一集合中,只能存储不可变的数据类型,包括整形、浮点型、字符串、元组,无法存储列表、字典、集合这些可变的数据类型,否则 Python 解释器会抛出 TypeError 错误。比如说:

>>> {{'a':1}}
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    {{'a':1}}
TypeError: unhashable type: 'dict'
>>> {[1,2,3]}
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    {[1,2,3]}
TypeError: unhashable type: 'list'
>>> {{1,2,3}}
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    {{1,2,3}}
TypeError: unhashable type: 'set'

4、 、set 集合是无序的,所以每次输出时元素的排序顺序可能都不相同

创建set集合

Python 提供了 2 种创建 set 集合的方法,分别是使用 {} 创建和使用 set() 函数将列表、元组等类型数据转换为集合。

1) 使用 {} 创建

在 Python 中,创建 set 集合可以像列表、元素和字典一样,直接将集合赋值给变量,从而实现创建集合的目的,其语法格式如下:

setname = {element1,element2,...,elementn}

其中,setname 表示集合的名称,起名时既要符合 Python 命名规范,也要避免与 Python 内置函数重名。

举个例子:

 
  1. a = {1,'c',1,(1,2,3),'c'}
  2. print(a)

运行结果为:

{1, 'c', (1, 2, 3)}

2) set()函数创建集合

set() 函数为 Python 的内置函数,其功能是将字符串、列表、元组、range 对象等可迭代对象转换成集合。该函数的语法格式如下:

setname = set(iteration)

其中,iteration 就表示字符串、列表、元组、range 对象等数据。
例如:

  1. set1 = set("c.biancheng.net")
  2. set2 = set([1,2,3,4,5])
  3. set3 = set((1,2,3,4,5))
  4. print("set1:",set1)
  5. print("set2:",set2)
  6. print("set3:",set3)

运行结果为:

set1: {'a', 'g', 'b', 'c', 'n', 'h', '.', 't', 'i', 'e'}
set2: {1, 2, 3, 4, 5}
set3: {1, 2, 3, 4, 5}

注意,如果要创建空集合,只能使用 set() 函数实现。因为直接使用一对 {},Python 解释器会将其视为一个空字典。

访问set集合元素

由于集合中的元素是无序的,因此无法向列表那样使用下标访问元素。Python 中,访问集合元素最常用的方法是使用循环结构,将集合中的数据逐一读取出来。
例如

  1. a = {1,'c',1,(1,2,3),'c'}
  2. for ele in a:
  3. print(ele,end=' ')

运行结果为:

1 c (1, 2, 3)

由于目前尚未学习循环结构,以上代码初学者只需初步了解,后续学习循环结构后自然会明白。

删除set集合

和其他序列类型一样,手动函数集合类型,也可以使用 del() 语句,例如:

  1. a = {1,'c',1,(1,2,3),'c'}
  2. print(a)
  3. del(a)
  4. print(a)

运行结果为:

{1, 'c', (1, 2, 3)}
Traceback (most recent call last):
  File "C:\Users\mengma\Desktop\1.py", line 4, in <module>
    print(a)
NameError: name 'a' is not defined

 set 集合中添加元素

set 集合中添加元素,可以使用 set 类型提供的 add() 方法实现,该方法的语法格式为:

setname.add(element)

其中,setname 表示要添加元素的集合,element 表示要添加的元素内容。

需要注意的是,使用 add() 方法添加的元素,只能是数字、字符串、元组或者布尔类型(True 和 False)值,不能添加列表、字典、集合这类可变的数据,否则 Python 解释器会报 TypeError 错误。例如:

 
  1. a = {1,2,3}
  2. a.add((1,2))
  3. print(a)
  4. a.add([1,2])
  5. print(a)

运行结果为:

{(1, 2), 1, 2, 3}
Traceback (most recent call last):
  File "C:\Users\mengma\Desktop\1.py", line 4, in <module>
    a.add([1,2])
TypeError: unhashable type: 'list'

set集合中删除元素

删除现有 set 集合中的指定元素,可以使用 remove() 方法,该方法的语法格式如下:

setname.remove(element)

使用此方法删除集合中元素,需要注意的是,如果被删除元素本就不包含在集合中,则此方法会抛出 KeyError 错误,例如:

 
  1. a = {1,2,3}
  2. a.remove(1)
  3. print(a)
  4. a.remove(1)
  5. print(a)

运行结果为:

{2, 3}
Traceback (most recent call last):
  File "C:\Users\mengma\Desktop\1.py", line 4, in <module>
    a.remove(1)
KeyError: 1

上面程序中,由于集合中的元素 1 已被删除,因此当再次尝试使用 remove() 方法删除时,会引发 KeyError 错误。

如果我们不想在删除失败时令解释器提示 KeyError 错误,还可以使用 discard() 方法,此方法和 remove() 方法的用法完全相同,唯一的区别就是,当删除集合中元素失败时,此方法不会抛出任何错误。

例如:

 
  1. a = {1,2,3}
  2. a.remove(1)
  3. print(a)
  4. a.discard(1)
  5. print(a)

运行结果为:

{2, 3}
{2set集合做交集、并集、差集运算

集合最常做的操作就是进行交集、并集、差集以及对称差集运算,首先有必要给大家普及一下各个运算的含义。


 


图 1 集合示意图


图 1 中,有 2 个集合,分别为 set1={1,2,3} 和 set2={3,4,5},它们既有相同的元素,也有不同的元素。以这两个集合为例,分别做不同运算的结果如表 1 所示。
 

表 1 Python set集合运算
运算操作Python运算符含义例子
交集&取两集合公共的元素>>> set1 & set2
{3}
并集|取两集合全部的元素>>> set1 | set2
{1,2,3,4,5}
差集-取一个集合中另一集合没有的元素>>> set1 - set2
{1,2}
>>> set2 - set1
{4,5}
对称差集^取集合 A 和 B 中不属于 A&B 的元素>>> set1 ^ set2
{1,2,4,5}

set集合方法详解(全)

方法名语法格式功能实例
add()set1.add()向 set1 集合中添加数字、字符串、元组或者布尔类型>>> set1 = {1,2,3}
>>> set1.add((1,2))
>>> set1
{(1, 2), 1, 2, 3}
clear()set1.clear()清空 set1 集合中所有元素>>> set1 = {1,2,3}
>>> set1.clear()
>>> set1
set()

set()才表示空集合,{}表示的是空字典
copy()set2 = set1.copy()拷贝 set1 集合给 set2>>> set1 = {1,2,3}
>>> set2 = set1.copy()
>>> set1.add(4)
>>> set1
{1, 2, 3, 4}
>>> set1
{1, 2, 3}
difference() set3 = set1.difference(set2)将 set1 中有而 set2 没有的元素给 set3>>> set1 = {1,2,3}
>>> set2 = {3,4}
>>> set3 = set1.difference(set2)
>>> set3
{1, 2}
difference_update()set1.difference_update(set2)从 set1 中删除与 set2 相同的元素>>> set1 = {1,2,3}
>>> set2 = {3,4}
>>> set1.difference_update(set2)
>>> set1
{1, 2}
discard()set1.discard(elem)删除 set1 中的 elem 元素>>> set1 = {1,2,3}
>>> set1.discard(2)
>>> set1
{1, 3}
>>> set1.discard(4)
{1, 3}
intersection()set3 = set1.intersection(set2)取 set1 和 set2 的交集给 set3>>> set1 = {1,2,3}
>>> set2 = {3,4}
>>> set3 = set1.intersection(set2)
>>> set3
{3}
intersection_update()set1.intersection_update(set2)取 set1和 set2 的交集,并更新给 set1>>> set1 = {1,2,3}
>>> set2 = {3,4}
>>> set1.intersection_update(set2)
>>> set1
{3}
isdisjoint()set1.isdisjoint(set2)判断 set1 和 set2 是否没有交集,有交集返回 False;没有交集返回 True>>> set1 = {1,2,3}
>>> set2 = {3,4}
>>> set1.isdisjoint(set2)
False
issubset()set1.issubset(set2)判断 set1 是否是 set2 的子集>>> set1 = {1,2,3}
>>> set2 = {1,2}
>>> set1.issubset(set2)
False
issuperset()set1.issuperset(set2)判断 set2 是否是 set1 的子集>>> set1 = {1,2,3}
>>> set2 = {1,2}
>>> set1.issuperset(set2)
True
pop()a = set1.pop()取 set1 中一个元素,并赋值给 a>>> set1 = {1,2,3}
>>> a = set1.pop()
>>> set1
{2,3}
>>> a
1
remove()set1.remove(elem)移除 set1 中的 elem 元素>>> set1 = {1,2,3}
>>> set1.remove(2)
>>> set1
{1, 3}
>>> set1.remove(4)
Traceback (most recent call last):
  File "<pyshell#90>", line 1, in <module>
    set1.remove(4)
KeyError: 4
symmetric_difference()set3 = set1.symmetric_difference(set2)取 set1 和 set2 中互不相同的元素,给 set3>>> set1 = {1,2,3}
>>> set2 = {3,4}
>>> set3 = set1.symmetric_difference(set2)
>>> set3
{1, 2, 4}
symmetric_difference_update()set1.symmetric_difference_update(set2)取 set1 和 set2 中互不相同的元素,并更新给 set1>>> set1 = {1,2,3}
>>> set2 = {3,4}
>>> set1.symmetric_difference_update(set2)
>>> set1
{1, 2, 4}
union()set3 = set1.union(set2)取 set1 和 set2 的并集,赋给 set3>>> set1 = {1,2,3}
>>> set2 = {3,4}
>>> set3=set1.union(set2)
>>> set3
{1, 2, 3, 4}
update()set1.update(elem)添加列表或集合中的元素到 set1>>> set1 = {1,2,3}
>>> set1.update([3,4])
>>> set1
{1,2,3,4}

frozenset集合

frozense和set区别

set 集合是可变序列,程序可以改变序列中的元素;frozenset 集合是不可变序列,程序不能改变序列中的元素。set 集合中所有能改变集合本身的方法,比如 remove()、discard()、add() 等,frozenset 都不支持;set 集合中不改变集合本身的方法,fronzenset 都支持。

我们可以在交互式编程环境中输入dir(frozenset)来查看 frozenset 集合支持的方法:

>>> dir(frozenset)
['copy', 'difference', 'intersection', 'isdisjoint', 'issubset', 'issuperset', 'symmetric_difference', 'union']

frozenset 集合的这些方法和 set 集合中同名方法的功能是一样的。

两种情况下可以使用 fronzenset:

  • 当集合的元素不需要改变时,我们可以使用 fronzenset 替代 set,这样更加安全。
  • 有时候程序要求必须是不可变对象,这个时候也要使用 fronzenset 替代 set。比如,字典(dict)的键(key)就要求是不可变对象。

下面程序演示了 frozenset 的用法:

  1. s = {'Python', 'C', 'C++'}
  2. fs = frozenset(['Java', 'Shell'])
  3. s_sub = {'PHP', 'C#'}
  4. #向set集合中添加frozenset
  5. s.add(fs)
  6. print('s =', s)
  7. #向为set集合添加子set集合
  8. s.add(s_sub)
  9. print('s =', s)

运行结果:

s = {'Python', frozenset({'Java', 'Shell'}), 'C', 'C++'}
Traceback (most recent call last):
    File "C:\Users\mozhiyan\Desktop\demo.py", line 11, in <module>
        s.add(s_sub)
TypeError: unhashable type: 'set'

需要注意的是,set 集合本身的元素必须是不可变的, 所以 set 的元素不能是 set,只能是 frozenset。第 6 行代码向 set 中添加 frozenset 是没问题的,因为 frozenset 是不可变的;但是,第 11行代码中尝试向 set 中添加子 set,这是不允许的,因为 set 是可变的。

Python浅拷贝和深拷贝

对于浅拷贝(shallow copy)和深度拷贝(deep copy),本节并不打算一上来抛出它们的概念,而是先从它们的操作方法说起,通过代码来理解两者的不同。

常见的浅拷贝的方法,是使用数据类型本身的构造器,比如下面两个例子:

  1. list1 = [1, 2, 3]
  2. list2 = list(list1)
  3. print(list2)
  4. print("list1==list2 ?",list1==list2)
  5. print("list1 is list2 ?",list1 is list2)
  6. set1= set([1, 2, 3])
  7. set2 = set(set1)
  8. print(set2)
  9. print("set1==set2 ?",set1==set2)
  10. print("set1 is set2 ?",set1 is set2)

运行结果为:

[1, 2, 3]
list1==list2 ? True
list1 is list2 ? False
{1, 2, 3}
set1==set2 ? True
set1 is set2 ? False

在上面程序中,list2 就是 list1 的浅拷贝,同理 set2 是 set1 的浅拷贝。

当然,对于可变的序列,还可以通过切片操作符“:”来完成浅拷贝,例如:

 
  1. list1 = [1, 2, 3]
  2. list2 = list1[:]
  3. print(list2)
  4. print("list1 == list2 ?",list1 == list2)
  5. print("list1 is list2 ?",list1 is list2)

运行结果为:

[1, 2, 3]
list1 == list2 ? True
list1 is list2 ? False


除此之外,Python 还提供了对应的函数 copy.copy() 函数,适用于任何数据类型。其用法如下:

 
  1. import copy
  2. list1 = [1, 2, 3]
  3. list2 = copy.copy(list1)
  4. print(list2)
  5. print("list1 == list2 ?",list1 == list2)
  6. print("list1 is list2 ?",list1 is list2)

运行结果为:

[1, 2, 3]
list1 == list2 ? True
list1 is list2 ? False


不过需要注意的是,对于元组,使用 tuple() 或者切片操作符 ':' 不会创建一份浅拷贝,相反它会返回一个指向相同元组的引用:

 
  1. tuple1 = (1, 2, 3)
  2. tuple2 = tuple(tuple1)
  3. print(tuple2)
  4. print("tuple1 == tuple2 ?",tuple1 == tuple2)
  5. print("tuple1 is tuple2 ?",tuple1 is tuple2)

运行结果为:

(1, 2, 3)
tuple1 == tuple2 ? True
tuple1 is tuple2 ? True

此程序中,元组 (1, 2, 3) 只被创建一次,t1 和 t2 同时指向这个元组。

看到这里,也许你可能对浅拷贝有了初步的认识。浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。

对数据采用浅拷贝的方式时,如果原对象中的元素不可变,那倒无所谓;但如果元素可变,浅拷贝通常会出现一些问题,例如:

 
  1. list1 = [[1, 2], (30, 40)]
  2. list2 = list(list1)
  3. list1.append(100)
  4. print("list1:",list1)
  5. print("list2:",list2)
  6. list1[0].append(3)
  7. print("list1:",list1)
  8. print("list2:",list2)
  9. list1[1] += (50, 60)
  10. print("list1:",list1)
  11. print("list2:",list2)

运行结果为:

list1: [[1, 2], (30, 40), 100]
list2: [[1, 2], (30, 40)]
list1: [[1, 2, 3], (30, 40), 100]
list2: [[1, 2, 3], (30, 40)]
list1: [[1, 2, 3], (30, 40, 50, 60), 100]
list2: [[1, 2, 3], (30, 40)]

此程序中,首先初始化了 list1 列表,包含一个列表和一个元组;然后对 list1 执行浅拷贝,赋予 list2。因为浅拷贝里的元素是对原对象元素的引用,因此 list2 中的元素和 list1 指向同一个列表和元组对象。

接着往下看,list1.append(100) 表示对 list1 的列表新增元素 100。这个操作不会对 list2 产生任何影响,因为 list2 和 list1 作为整体是两个不同的对象,并不共享内存地址。操作过后 list2 不变,list1 会发生改变。

再来看,list1[0].append(3) 表示对 list1 中的第一个列表新增元素 3。因为 list2 是 list1 的浅拷贝,list2 中的第一个元素和 list1 中的第一个元素,共同指向同一个列表,因此 list2 中的第一个列表也会相对应的新增元素 3。

最后是 list1[1] += (50, 60),因为元组是不可变的,这里表示对 list1 中的第二个元组拼接,然后重新创建了一个新元组作为 list1 中的第二个元素,而 list2 中没有引用新元组,因此 list2 并不受影响。

通过这个例子,你可以很清楚地看到使用浅拷贝可能带来的副作用。如果想避免这种副作用,完整地拷贝一个对象,就需要使用深拷贝。所谓深拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。

Python 中以 copy.deepcopy() 来实现对象的深度拷贝。比如上述例子写成下面的形式,就是深度拷贝:

 
  1. import copy
  2. list1 = [[1, 2], (30, 40)]
  3. list2 = copy.deepcopy(list1)
  4. list1.append(100)
  5. print("list1:",list1)
  6. print("list2:",list2)
  7. list1[0].append(3)
  8. print("list1:",list1)
  9. print("list2:",list2)
  10. list1[1] += (50, 60)
  11. print("list1:",list1)
  12. print("list2:",list2)

运行结果为:

list1: [[1, 2], (30, 40), 100]
list2: [[1, 2], (30, 40)]
list1: [[1, 2, 3], (30, 40), 100]
list2: [[1, 2], (30, 40)]
list1: [[1, 2, 3], (30, 40, 50, 60), 100]
list2: [[1, 2], (30, 40)]

可以看到,无论 list1 如何变化,list2 都不变。因为此时的 list1 和 list2 完全独立,没有任何联系。

不过,深度拷贝也不是完美的,往往也会带来一系列问题。如果被拷贝对象中存在指向自身的引用,那么程序很容易陷入无限循环,例如:

 
  1. import copy
  2. list1 = [1]
  3. list1.append(list1)
  4. print(list1)
  5. list2 = copy.deepcopy(list1)
  6. print(list2)

运行结果为:

[1, [...]]
[1, [...]]

此例子中,列表 x 中有指向自身的引用,因此 x 是一个无限嵌套的列表。但是当深度拷贝 x 到 y 后,程序并没有出现栈溢出的现象。这是为什么呢?

其实,这是因为深度拷贝函数 deepcopy 中会维护一个字典,记录已经拷贝的对象与其 ID。拷贝过程中,如果字典里已经存储了将要拷贝的对象,则会从字典直接返回。通过查看 deepcopy 函数实现的源码就会明白:

 
  1. def deepcopy(x, memo=None, _nil=[]):
  2. """Deep copy operation on arbitrary Python objects.
  3. See the module's __doc__ string for more info.
  4. """
  5. if memo is None:
  6. memo = {}
  7. d = id(x) # 查询被拷贝对象 x 的 id
  8. y = memo.get(d, _nil) # 查询字典里是否已经存储了该对象
  9. if y is not _nil:
  10. return y # 如果字典里已经存储了将要拷贝的对象,则直接返回
  11. ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值