作者germun (ger)
看板Python
标题Re: [问题] 关於赋值
时间Mon Feb 4 01:38:26 2019
※ 引述《nevikw39 (牧)》之铭言:
: 如题,Python 的变数系统至今对我仍然是个谜。
:
: Python 既是动态语言,变数感觉倾向於强型别但又不需要再宣告。因此,直译器到底是怎
: 麽判断型别的?而且,同一个变数名称前後可能指涉不同型别。
:
虽然python没有指标, 但没有指标观念的话很容易落入陷阱
没有指标或物件导向观念的话最好先去懂
首先python没有变数(variable), 只有`name`
(我不知怎麽翻, 所以以下全称name)
用`赋名`形容比较合适, 只是我们有时还是习惯用变数来称呼
所谓name的意思, 就是等号左边只是个名称, 将其名称指到右边的物件
所有物件的属性定义全都是依右边assign的物件来决定,
所以才不需事先宣告, 因为物件在建立时已有它的型态和各种资料
等号只是将 name 指到该物件, 或反过来说: 给右边的物件取一个 name
例如:
==========
a = 2
b = 2
==========
若从C的角度来开, 是将a跟b的值设成2,
但从python来看, 任何数字或任何字串本身也都是物件
这边是分别将 a 跟 b 指到 `2` 这个int物件
所以 id(a) == id(b) 跟 id(a) == id(2) 会是True, 因为都指到同一物件 `2`
接着再一行
===========
b = 4
===========
正确的解读是将 b `重新指向` 4 这个物件
: 主要想请教的是 dict 和 list 的部分:
: # base 读自 json
: def callback(e):
: ...
: data = base
从这一行来解读
base是已存在的name, 已经有其指向的物件 (举例来说是个字串"abc"好了)
那麽base其实只是个指向"abc"的 name
这行的结果就只会是:
=> 新建一个name `data`, 指向`base`所指的物件
白话讲就是, base指向谁, 那麽data也同样指向谁
也就是:
base -> "abc"
data -> "abc"
两者 "abc" 是同记忆体位置的同一物件
因而你透过 `data[...] = XXX` 去改动的元素内容, 对应的`base[...]`也会改动
但你若直接:
======
data = "ddd"
======
这时就会是将data重新指向一个新物件 "ddd", 而不会改动base的内容
: data[...] = ...
: 这样好像会改动到原本 base 的值欸?
: 还有例如:
: lst = []
lst是个物件 `[]`
: a = [0, 0, 0]
a也是个物件 `[0, 0, 0]`
: lst.append(a)
把a放入lst
此时lst[0] 会指向 a 所指的物件
id(lst[0]) == id(a) 为 True
: for i in range(len(a)):
: a[i] += 1
a还是同一个list, 记忆体位置不变, 但里面元素所指的物件都变成1
即 a[0], a[1], ... = 1, 1, ...
到这时你lst[0]里面已经跟着变成 [1,1,1], 因为是同一个list
ps. 要注意这跟 `a = [1,1,1]` 是不同行为, 这是重新建新的list
: lst.append(a)
再一次把a放进去,
所以lst[0], lst[1]都是同一个list,
一改内容两个就一起改了
: 结果 lst 的值不是 [[0, 0, 0], [1, 1, 1]] ,而是 [[1, 1, 1], [1, 1, 1]] 欸!
: 所以,当我作 data = base 这个运算时,感觉只是将 data 参考指向 base 这个实体而已
: ,而我若 lst.append(a) 也只是把 lst 的尾端指向 a。那麽,Python 的指派究竟何时是
: 参考,何时是复制呢?
你如果一定要用list的话, 那就一定要先建一个新list
例如 b = [], 再把值丢进去
或直接复制内容:
b = a[:]
这样的解读相当於:
b = [a[0], a[1], ....]
把a的元素分别取出重新建一个list, 如此a跟b就会是不同list
甚至是
a = a[:] # 重新建一个list `a`, 原本的list a遗失,
但这边原本的 a 已经放入`lst`中所以无妨
但要注意这边不会出错是因为a[0]本身是指向int物件, 因此不会有问题
如果 a[0] 指向的是list这类物件, 也就是你的 a 若是二维以上的list,
或其他具有属性的物件, 那又会回到上述状况了
如果你要用到2维以上来计算值, 例如矩阵
那麽用numpy array是比较容易
不过numpy array跟list又有微妙不同之处, 那又是另一回事了
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.160.131.38
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Python/M.1549215510.A.E65.html
1F:推 XperiaZ6C: 推 02/04 05:30
2F:推 yangs0618: 那如果data指向base再把base改指向跟原本不同呢 02/04 12:25
3F:推 s06yji3: data不变 02/04 16:42
4F:推 s06yji3: 因为只是将base这个名字绑到其他物件而已 02/04 16:43
5F:推 utap2001: 所以Python跟c,java的逻辑不同,是把等号左边指向右边 02/08 21:42