Re: [问题] 关于赋值

楼主: germun (ger)   2019-02-04 01:38:26
※ 引述《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又有微妙不同之处, 那又是另一回事了
作者: XperiaZ6C (真●安卓轻旗舰)   2019-02-04 05:30:00
作者: yangs0618 (阿彰)   2019-02-04 12:25:00
那如果data指向base再把base改指向跟原本不同呢
作者: s06yji3 (阿南)   2019-02-04 16:42:00
data不变因为只是将base这个名字绑到其他物件而已
作者: utap2001 (寻找一个漫长的答案 )   2019-02-08 21:42:00
所以Python跟c,java的逻辑不同,是把等号左边指向右边

Links booklink

Contact Us: admin [ a t ] ucptt.com