Python
239 浏览 1 year, 11 months
1.1 变量
版权声明: 转载请注明出处 http://www.codingsoho.com/变量
概述
变量是什么? 在数学里,我们用下面的格式来表示变量
3y = 2x + 1 + 2y
x = 7
3y - 2y = 2x + 1
x = 7
y = 2x + 1
x = 7
y = 2*7 + 1
x = 7
y = 15
x = 7
在C/C++里,表示方法如下:
int a = 1;
...
a = 3;
在数学和C++里,变量可以认为是计算过程中间值得一个存储位置。
<font color='red'>在python中呢?</font>
下面是代码的比较:
C++:
#include <array>
#include <iostream>
using namespace std;
int main() {
cout<<" a b \n";
array<int,1> a = {1};
cout<<"["<<a[0]<<"]\n";
a[0] = 3;
cout<<"["<<a[0]<<"]\n";
array<int,1> b = a;
cout<<"["<<a[0]<<"] ["<<b[0]<<"]\n";
a[0] = 4;
cout<<"["<<a[0]<<"] ["<<b[0]<<"]\n";
b[0] = 5;
cout<<"["<<a[0]<<"] ["<<b[0]<<"]\n";
return 0;
}
//>
python
#!/usr/local/bin/python2.7
print ' a b '
a = [1]
print a
a[0] = 3
print a
b = a
print a, b
a[0] = 4
print a, b
b[0] = 5
print a, b
C++的在线编译运行可以访问网址 http://www.compileonline.com/compile_cpp11_online.php
输出结果如下:
C++
a b
[1]
[3]
[3] [3]
[4] [3]
[4] [5]
python
a b
[1]
[3]
[3] [3]
[4] [4]
[5] [5]
为什么python的结果会不一样呢?
其他语言的赋值过程如下图
每一个变量都是一个<font color='red'>容器(存储空间)</font>,向一个变量赋值相当于把一个值放到这个盒子里。
例如int a=1;
, a盒子里会包含整数1
向这个变量赋另外一个值时,会替换盒子里的内容,执行a=2;
, 盒子里的内容变成了2
将一个变量赋值给另外一个变量时,实际上时把当前变量值得拷贝放到新的盒子里,int b=a;
, 变量b是一个新的盒子,里面放的是变量a的内容的拷贝
Python里的情况就有点不同,变量更像是一个<font color='red'>名字,绑定到某个对象</font>
例如a=1;
,这儿整数1是一个对象,a是绑定到这个对象的标签;
如果给a重新分配对象,实际只是将这个标签移到另外的对象;
a=2
, 标签a从对象1绑定移到对象2;原来的对象1将失去标签a,这个对象可能还是存在的,但是我们已经不能通过a来访问了。
通常一个对象如果没有引用或者标签,它将会被从内存里删除。
如果我们将一个标签名赋值给另外一个标签,实际上是将新的标签同时绑定到这个对象上。
b=a
, b和a将会绑定到同一个对象上去。
所以,在python里,变量只是一个名字或者ID,它不是一个存储的盒子。
变量赋值
Python中变量在使用前需要赋值,变量赋值不需要事先声明类型
Python使用=
号类给变量赋值:左边是变量名,右边是值
a=1,b=0.5, c='abc',d=(1,2,3),e=[1,2,3],f={1,2,3}
Python支持多变量赋值
a=b=c=1, a,b,c = 1,1.1,'aaa'
对于变量键盘输入赋值,使用input()
函数:
>>> a = input("please input your number:")
please input your number:12
>>> a
'12'
>>>
多态 polymorphic
多态的意思是说变量可以分配不同类型的值,因为python里变量只是一个绑定到实际值的名字而已,所以它天生就是多态的。
引用 References
看下面一段C++代码
int a = 1;
int &b = a;
b = 2;
它对应的过程图解如下
C++里,变量可以是引用,它是位置的别名。一旦绑定之后就不能再改变,重新分配也不会改变引用。所以上例b=2
不会改变b。
python里,变量是值得名字,所以所有变量都是引用。一个变量不能是另外一个引用/变量的引用。分配会改变引用本身。如下图
可以看到,在C++或者其他语言里,变量是一个存储位置,你会向这个位置写值(例如,整型,对象或者指针);引用是一个存储位置的别名,当你分配给一个非引用的变量时,你会向这个存储位置拷贝一个值,如果你分配给是引用,将会拷贝到其他的某个位置。
注意:你无法改变引用本身,一旦绑定,所有向它的赋值不会改变引用本身,只会修改它引用的内容。
在python里,变量只是个名字。值是在其他某个地方,变量关联到它。多个名字可以引用同一个值. python里将这种绑定到其他值的方式叫做引用,尽管这个跟C++里的引用不太一样。分配一个变量就是简单的将它引用到那个值。存储位置的模型不适用于python,程序员不需要处理值的存储位置。
变量标识符
在Python 里,标识符由字母、数字、下划线组成,区分大小写,但不能以数字开头。
另外,一些变量标识符有特殊的意义:
- 以下划线
_
开头的标识符是有特殊意义的。以单下划线开头_foo
的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用from xxx import *
而导入; - 以双下划线
__
开头的__foo
代表类的私有成员;以双下划线开头和结尾的__foo__
代表Python 里特殊方法专用的标识,如__init__()
代表类的构造函数。 - Python保留标识符有特殊的意义,不能用作变量定义
import keyword; keyword.kwlist # 可以列出所有保留关键字
作用域解析 scope resolution LEGB
- L : Local 函数内分配的一个名字(def或lambda),没有全局声明
- E : Enclosing function locals 外部嵌套函数的名字空间
- G : Global 定义在module文件的顶部
- B : Built-In 内置模块的名字
在python里,函数定义会引入一个新的作用域,当调用嵌套函数和lambda时,会引入更多的作用域。嵌套函数能够访问本地作用域,以及在封闭函数 内的内容。
例子:
内部作用域之外的变量是只可读的,如果尝试去写这个变量的话,只是在内部作用域创建一个新的变量,外部的那个变量保持不变。
对于嵌套函数来说,也是相同的规则
global_var = [1,2]
def func():
global_var = [4,5]
nonlocal local1 = 4
def embedded_func():
# Won't affect func's local1.
# Create new local variable
# (also called local1).
local1 = 5
print(local1) # Prints 5
print(local1) # Prints 4
# return embedded_func
如果我就是想在函数作用域内部修改全局变量的绑定,该怎么做呢?通过"global"关键字
global_var = "ab"
def change_global():
global global_var
global_var = "bb"
上面函数中,先声明global_var是一个全局变量,然后就可以重新绑定该变量了,不管你的嵌套有多深,它都不会创建一个新的本地变量。
如果想改变外部嵌套函数内的变量可以用nonlocal,nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量。
def func():
local1 = 4
def embedded_func():
nonlocal local1
local1 += 1
return local1
return embedded_func
val = func()
print(val())
print(val())
print(val())
>>> val = func()
>>> print(val())
5
>>> print(val())
6
>>> print(val())
7
声明local1为nonlocal变量后,函数外的变量也被修改了
global和nonlocal的差别
- 第一,两者的功能不同。global关键字修饰变量后标识该变量是全局变量,对该变量进行修改就是修改全局变量,而nonlocal关键字修饰变量后标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal位置会发生错误(最上层的函数使用nonlocal修饰变量必定会报错)。
- 第二,两者使用的范围不同。global关键字可以用在任何地方,包括最上层函数中和嵌套函数中,即使之前未定义该变量,global修饰后也可以直接使用,而nonlocal关键字只能用于嵌套函数中,并且外层函数中定义了相应的局部变量,否则会发生错误(见第一)。
练习
已知a = [1, 2, 3]和b = [1, 2, 4],那么id(a[1])==id(b[1])的执行结果 ()
答案:True, python中对于小整数对象有一个小整数对象池,范围在[-5,257)之间。
对于在这个范围内的征数,不会新建对象,直接从小整数对象池中取就行。
a = [1, 2, 3]
b = [1, 2, 4]
id(a[1])==id(b[1])
True