前一篇我们聊了一些字典有趣的取值方式,所以接下来我想接着继续聊关於字典的部分。
在 JavaScript 中我们时常会使用到两个很好用的 ES6 语法取出物件属性名称与物件属性值,没有错,就是 Object.keys()
、Object.values()
,而这两个语法都有异曲同工之处,底层实作会将物件中的属性名称与值使用 for...in
全部跑过一次并回传其结果,而回传的结果会是一个阵列。
以 Object.keys()
来讲就是回传物件的属性:
var obj = {
myName: 'Ray',
a: '1',
b: '2',
fn() {
console.log('123')
}
};
console.log(Object.keys(obj)); // [ "myName", "a", "b", "fn" ]
而 Object.values()
则是回传属性的值:
var obj = {
myName: 'Ray',
a: '1',
b: '2',
fn() {
console.log('123')
}
};
console.log(Object.values(obj)); // [ "Ray", "1", "2", fn() ]
可以看到如果是函式的话,就会直接回传你一个函式。
那麽 Python 也有相同的功能吗?有的,一样也是叫做 keys
、values
:
dis = {
'myName': 'Ray',
'a': '1',
'b': '2',
}
print(dis.keys()) # dict_keys(['myName', 'a', 'b'])
print(dis.values()) # dict_values(['Ray', '1', '2'])
看到 dict_keys
、dict_values
,不用太害怕,它只是告诉你这是字典的 keys
与 values
而已。
但是这边要注意,如果你直接使用 dis.keys()[0]
取值是会出现错误的:
dis = {
'myName': 'Ray',
'a': '1',
'b': '2',
}
print(dis.keys()[0]) # TypeError: 'dict_keys' object is not subscriptable
有没有觉得自己好像被阴了一下?
毕竟我们在 JavaScript 中使用 Object.keys()
、Object.values()
之後就可以直接执行一些阵列操作方法,但是在 Python 是必须额外处理的,因此你必须使用 list()
将它转换成串列,这样子才能够正确的取值:
dis = {
'myName': 'Ray',
'a': '1',
'b': '2',
}
print(list(dis.keys())[0]) # myName
print(list(dis.values())[0]) # Ray
最後一个则是 Python 的 items
方法,而 items
与 JavaScript 的 Object.entries
非常雷同,会将属性与值一起都回传出来:
var obj = {
myName: 'Ray',
a: '1',
b: '2',
};
console.log(Object.entries(obj)); // [ [ "myName", "Ray" ], [ "a", "1" ], [ "b", "2" ] ]
但是在讲 items
方法之前,先让我跳来讲另一个前面没有讲到的东西东西也就是 元组(Tuple)。
元组很特别,它是一个类似串列的容器,看到这边可能有些写过 TypeScript 的人会很兴奋,毕竟 TypeScript 中也有一个叫做元组的型别:
const a: [string, number];
a = ['Ray', 1];
console.log(a[0]); // Ray
但是在 Python 的元组宣告方式是使用括号 ()
来宣告,除此之外它还有一个特性,元组是 read only (唯读) 的,当你宣告了这个元组之後你就无法再更改它,但取值的方式与串列没有差异:
tpe = (1, 2, 3)
print(tpe[0]) # 1
只要你做出了修改值的行为就会出现错误:
tpe = (1, 2, 3)
tpe[0] = 10 # TypeError: 'tuple' object does not support item assignment
print(tpe[0])
所以如果你有需要修改的需求,那麽还是会建议你使用串列就好:
tpe = [1, 2, 3]
tpe[0] = 10
print(tpe) # [10, 2, 3]
回到 items
的部分,为什麽要先讲元组呢?因为使用 items
取出来的字典会是一个元组:
dis = {
'myName': 'Ray',
'a': '1',
'b': '2',
}
print(list(dis.items())) # [('myName', 'Ray'), ('a', '1'), ('b', '2')]
这就是为什麽要先拉过来介绍元组了,因为使用 items
取出来的串列都会是唯读不可修改:
dis = {
'myName': 'Ray',
'a': '1',
'b': '2',
}
print(list(dis.items())) # [('myName', 'Ray'), ('a', '1'), ('b', '2')]
print(list(dis.items())[0]) # ('myName', 'Ray')
print(list(dis.items())[0][1]) # 'Ray'
list(dis.items())[0][1] = 'Ray2' # TypeError: 'tuple' object does not support item assignment
虽然我们前面有说明到元祖本身是 read only (唯读):
tup = (1, 2, 3)
tup[0] = 1 # TypeError: 'tuple' object does not support item assignment
可是如果今天修改的是元组内的字典属性可以不可以呢?答案基本上是可以的:
tup = ({
'myName1': 'Ray1'
},{
'myName2': 'Ray2'
})
tup[0]['myName1'] = 'QQ'
那麽这是为什麽?主要原因是我们是修改的字典中的属性,并不是修改本身元组所指向的字典记忆点位置,因此就可以修改字典的值,甚至是新增另一个属性也可以:
tup = ({
'myName1': 'Ray1'
},{
'myName2': 'Ray2'
})
tup[0]['myName1'] = 'QQ'
tup[0]['blog'] = 'Welcome.Web.World - Ray Blog'
除非你今天是重新指向给它新的字典位置才会出现错误:
tup = ({
'myName1': 'Ray1'
},{
'myName2': 'Ray2'
})
tup[0]['myName1'] = 'QQ'
tup[0]['blog'] = 'Welcome.Web.World - Ray Blog'
tup[0] = {} # TypeError: 'tuple' object does not support item assignment
而这边的概念就 JavaScript 中的 const obj = {};
的概念是非常雷同的唷。
最後额外补充聊一下 in
运算子,基本上这个运算子的概念就如同 JavaScript 的 Object.hasOwnProperty
方法,hasOwnProperty
可以用於寻找该属性是否存在於这个物件中:
var obj = {
myName: 'Ray',
}
obj.hasOwnProperty('myName'); // true
而 Python 中的 in
运算子也是一样的存在,如果存在就会回传 True
,如果不存在就是 False
,但是这个运算子的写法是属性在前,字典在後:
dis = {
'myName': 'Ray',
'a': '1',
'b': '2',
}
print('myName' in dis) # True
透过阅读程序码就可以很明确的知道这一段正在表达「字串 myName
在不在 dis
字典中。」这一段话。
题外话,其实 JavaScript 也有 in
运算子,只是我自己很少使用:
var obj = {
myName: 'Ray',
}
console.log('myName' in obj); // true
这几天算是把花雕酒给消耗完毕了,但是跑去逛全联时却一个脑弱不小心又败了一瓶绍兴酒回来...看来又要开始制作醉鸡之路了...
>>: 每个人都该学的30个Python技巧|技巧 11:回圈二部曲—while回圈(字幕、衬乐、练习)
介绍 html(Hypertext Markup Language)是一种标记语言,就是里面的标记有...
这篇会写如何设计 DDE 语料库,还有 DDE 设计的逻辑。 终於来到第五篇,这次截图比较多,主要是...
基於上篇,有了数据特徵,再来就可以把欧氏距离发展为马氏距离公式 马氏距离公式(Mahalanobis...
其实插入排序法就很像平时我们在玩扑克牌时整理牌组的行为,将扑克牌依照大小插入对应的位置,插入排序法...
Spinner下拉式选单 这也很常用在表单中 如:选择地区、居住地、选择语言、学校 那今天就来学习点...