Python变量,变量的概念基本上和初


4.10 Python变量

4.10.1 变量介绍

变量,顾名思义,就是可以变化的量。变量的概念基本上和初中代数的方程变量是一致的,只是在计算机程序中,变量不仅可以是数字,还可以是任意数据类型。
Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。
在 Python中,变量就是变量,它没有类型,我们所说的类型是变量所指的内存中对象的类型。如果有个数据不被任何变量所指向,则会被Python的回收机制回收掉,以节省内存。
在Python中,一切皆对象。所以其实:变量就是对象的名字!

4.10.2 变量名

变量在程序中需要用变量名进行表示,在Python中,变量的命名是需要满足一定的条件的:

  1. 允许包括英文(中文等其他国家文字也可以)、数字以及下划线_,不能以数字开头
  2. 名称区分大小写,例如:fun和Fun是不同的变量名。
  3. 不要使用关键字作为变量名,这可能会导致未知的错误。
    以下是一些变量命名的建议:
  4. 以_开头的变量是有特殊意义的,最好不要创建以_开头的变量名。
  5. 变量命名建议采用驼峰命名法(MyName、UserId)或蛇形命名法(my_name、user_id)。
  6. 特殊变量或者常量建议全部大写。
  7. 类名建议使用驼峰命名法。
  8. 变量名最好要做到见名知意。

4.10.3 变量的赋值

赋值运算符=用来给变量赋值。=左边是一个变量名,=右边是存储在变量中的值。
>>> counter = 100 # 整型变量
>>> miles = 1000.0 # 浮点型变量
>>> name = "atom" # 字符串
>>> a = b = c = 1 # 链式赋值
>>> a, b, c = 1, 2, 3 # 多个变量同时复制
>>> a, *b, c = 1, 2, 3, 4, 5 # 装包
>>> a, b = b, a # 交换变量
>>> a, b, c = [1, 2, 3] # 解包赋值
>>> x += 1 # 增强赋值
在Python中,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,这点和其它编程语言有所不同。因此,Python是一种动态语言,而与之对应的静态语言在变量赋值时需要先定义变量类型,如果后续赋值时类型和定义时不匹配,就会报错。
和静态语言相比,动态语言更加灵活。
让我们来看看在Python中变量赋值时发生了什么。当我们将atom赋值给name时:
>>> name = 'atom'
Python解释器会先在内存中创建一个atom的字符串,然后再创建一个名为name的变量,并指向atom
我们可以想象有个箱子,里面装了一个数据,就是字符串的atom,而变量就像是一个标签,标签名是name,贴在了刚才的箱子上。如果是贴在装有100数字类型的箱子上,那么这个变量就是100。
在Python中,一定要牢记一点:变量无类型,数据才有类型。变量就是个标签,贴在什么数据上,就是什么数据类型。下面这个例子能很好的说明这一点:

a = 100
b = a
a = 'string'
print(f'a: {a}')
print(f'b: {b}')

a: string
b: 100

4.10.3.2 Python中表示常量

所谓常量就是不能变的变量,比如常用的数学常数π就是一个常量。在Python中,通常用全部大写的变量名表示常量:
>>> PI = 3.14
但事实上PI仍然是一个变量,Python根本没有任何机制保证PI不会被改变,所以,用全部大写的变量名表示常量只是一个习惯上的用法。

4.10.3.3 浅复制、深复制

前面我们讲过可以通过id()函数获取某个对象的id,这个id对于每个数据都是不同的。如果两个变量的id一样,那么则说明这两个变量指向同一个对象。

a = 'str'
b = [1, 2, 3]
c = {1: [22, 33]}
aa = a
bb = b
cc = c
print(id(a) == id(aa))
print(id(b) == id(bb))
print(id(c) == id(cc))
print(id(c[1]) == id(cc[1]))

True
True
True
True

像上面,通过=进行复制的一般称为浅复制(比如:aa = a),浅复制后,aa和a这两个变量其实指向的都是同一个数据。所以具有一样的id。只要修改了原始数据后,所有通过浅复制指向这个数据的变量的值都会发生变化:

b = [1, 2, 3]
bb = b
b.pop()
print(f'b: {b}')
print(f'bb: {bb}')

b: [1, 2]
bb: [1, 2]

我们可以通过导入copy模块中的deepcopy函数来进行深复制。对于不可变数据,比如:元组或字符串等,深复制后指向的还是同一个数据。与浅复制没有区别。但是对于可变数据,比如:列表和字典,深复制后,虽然变量的值还是一样,但是指向的数据已经不是同一个了。如下:

from copy import deepcopy
a = 'str'
b = [1, 2, 3]
c = {1: [22, 33]}
aaa = deepcopy(a)
bbb = deepcopy(b)
ccc = deepcopy(c)
print(id(a) == id(aaa))
print(id(b) == id(bbb))
print(id(c) == id(ccc))
print(id(c[1]) == id(ccc[1]))

True
False
False
False

深复制后,由于指向的不是相同的数据,于是,修改其中一个变量后,并不会影响到其它变量。如下:

from copy import deepcopy

b = [1, 2, 3]
bb = deepcopy(b)
print(id(b) == id(bb))
b.pop()
print(f'b: {b}')
print(f'bb: {bb}')

False
b: [1, 2]
bb: [1, 2, 3]

4.10.4 变量的作用域

根据变量的作用范围,可以将变量分为:局部变量和全局变量。

4.10.4.1 局部变量

在函数、类、方法等内部定义的变量,它的作用域也仅限于其定义时的内部,在外部则不能使用,我们将这样的变量称为局部变量(Local Variable)。
当函数或类被执行时,Python 会为其分配一块临时的存储空间,所有在函数、类中定义的变量,都会存储在这块空间中。而在函数、类执行完毕后,这块临时存储空间随即会被释放并回收,该空间中存储的变量自然也就无法再被使用。

def add(a, b):
    c = 10
    print(c)
    print(a+b)


add(1, 2)
print(c)

10
3
Traceback (most recent call last):
File "E:\studypy\tmp.py", line 6, in
print(c)
NameError: name 'c' is not defined

如上,在add函数中定义了一个变量c,并赋值为10,调用add函数时是可以正常打印出来c的。但是在函数外面打印则报错:name 'c' is not defined
正常情况下,在定义的内部结构体中可以获取和使用局部变量,也可以对局部变量进行修改和删除。
如果想要在外部使用内部变量,则需要在变量前面加上关键字global进行声明。声明该变量是一个全局变量。

def add(a, b):
    global c
    c = 10
    print(c)
    print(a + b)


add(1, 2)
print(c)

10
3
10

4.10.4.1.1 locals()函数

通过locals()函数,我们可以得到一个包含当前作用域内所有变量的字典。这里所谓的“当前作用域”指的是,在函数内部调用 locals() 函数,会获得包含所有局部变量的字典;而在全局范围内调用 locals() 函数,其功能和 globals() 函数相同。
注意:
1、locals() 函数返回的字典中,会默认包含有很多变量,这些都是 Python 主程序内置的,我们暂时不用理会它们。
2、我们无法可以通过修改上面获得的字典来修改局部变量的值。

def myprint():
    name = 'zhangsan'
    print(locals()['name'])
    locals()['name'] = "lisi"
    print(name)


myprint()

zhangsan
zhangsan

4.10.4.1.2 vars(object)函数

vars()函数也是 Python 内置函数,其功能是返回一个指定 object 对象(对于函数不起作用)范围内所有变量组成的字典。如果不传入object 参数,vars() 和 locals() 的作用完全相同。

name = "Python"
class Demo:
    name = "Python 教程"
print(vars(Demo))
print(vars())

{'module': 'main', 'name': 'Python 教程', 'dict': <attribute 'dict' of 'Demo' objects>, 'weakref': <attribute 'weakref' of 'Demo' objects>, 'doc': None}
{'name': 'main', 'doc': None, 'package': None, 'loader': <_frozen_importlib_external.SourceFileLoader object at 0x0000017DD89A7C40>, 'spec': None, 'annotations': {}, 'builtins': <module 'builtins' (built-in)>, 'file': 'E:\studypy\tmp3.py', 'cached': None, 'name': 'Python', 'Demo': <class 'main.Demo'>}

4.10.4.2 全局变量

在模块内定义的变量称为全局变量(Global Variable),和局部变量不同,全局变量的默认作用域是整个程序,即全局变量可以在所有函数、类、类方法中直接使用。

c = 5
def add(a, b):
    print(f'c: {c}')
    print(f'a+b={a + b}')
add(1, 2)

c: 5
a+b=3

globals() 函数为 Python 的内置函数,它可以返回一个包含全局范围内所有变量的字典,该字典中的每个键值对,键为变量名,值为该变量的值。
注意,globals() 函数返回的字典中,会默认包含有很多变量,这些都是 Python 主程序内置的,我们暂时不用理会它们。
可以看到,通过调用 globals() 函数,我们可以得到一个包含所有全局变量的字典。并且,通过该字典,我们还可以访问指定变量,甚至如果需要,还可以修改它的值。

name = 'zhangsan'
print(globals()['name'])
globals()['name'] = "lisi"
print(name)

zhangsan
lisi

从自动化办公到智能化办公

评论关闭