变量

1. 什么是变量

 变量是内存中某个值的名称,变量的值其实是该值的内存地址,而不是其值/内容。只是直观感觉是内存的值。

另外python是动态语言即一个变量的类型是由其值决定的。python没有像java语言的声明,eg:String name;声明时就指定的变量的类型。

 

2. 变量的作用是什么?

 

1. 程序使用的数据,存储在内存中,而变量就代表其中1个数据,变量的值就是该数据的内存地址。即变量是内存地址(数据),直观上看变量就是内存的1个数据。是程序员与内存数据沟通的桥梁。

2. 变量名不仅可以帮助我们记住每个值的含义,还可以帮助我们在程序中引用这些值。

3. 变量的命名(标识符)

3.1 标识符

Python 标识符是用于命名不同程序实体,如变量、函数、类、模块等的名称。以下是 Python 标识符的规定:

  1. 由连续的数字、字母(大小写都可以)和下划线 _ 组成,但是不能以数字开头。即不能包含空格或其他特殊字符,如 @#$% 等。

  2. Python 是大小写敏感的,因此 hello 和 Hello 是不同的标识符。

  3. 标识符的长度没有限制。

  4. 避免使用 Python 中的关键字 (reserved words),如 ifelsewhileforclassdef 等等。Python 中有 33 个关键字,它们是保留的,用于特定的语法和功能目的。

以下是一些符合 Python 标识符规定的示例:

1 hello_world  # 只包含字母和下划线的标识符 
2 num_123  # 包含数字、字母和下划线的标识符 
3 ThisIsCamelCase  # 驼峰式命名法的标识符 
4 _123test  # 以下划线 `_` 开头的标识符 

不符合 Python 标识符规定的示例:

1 2cats  # 标识符以数字开头
2 my-name  # 标识符包含横线 `-` 
3 test@you  # 标识符包含特殊字符 `@`
4 while = 10  # 标识符是关键字

查看python内置关键字的方法:

1 import keyword
2 
3 print(keyword.kwlist)

 

# 关键字列表
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

 

3.2 标识符命名规范

常见的3种命名风格:

1. 大驼峰:即每个单词首字母大写,eg:ClassName

2. 小驼峰:首字母小写,其他的单词首字母大写,eg:className

3. 下划线(也叫蛇形):全部小写,多个单词之间使用下划线连接,eg:class_name

 

在满足标识符的基本要求的基础上,团队需要统一风格。建议:

  1. 变量、函数、类和模块等名称应该清晰地描述它们的用途。要避免使用与 Python 内置函数或关键字相同的名称。

  2. 避免使用单字符名称:尽量避免使用单字符名称(例如 x 或 y),除非变量的用途非常清晰明确。

  3. 学习和使用 Python 的内置函数和模块的名称。

  4. 变量和函数的命名:在 Python 中,变量和函数通常使用小写字母和下划线来命名,例如:

1 my_variable = 42
2 def my_function():
3     pass

      5. 类和异常的命名:在 Python 中,类和异常通常使用首字母大写的驼峰命名法,例如:

1 class MyClass:
2     pass
3 
4 class MyCustomException(Exception):
5     pass

      6. 模块和包的命名:在 Python 中,模块和包通常使用小写字母和下划线命名,例如:

1 my_module.py
2 my_package/
3     __init__.py
4     my_submodule.py

      7. 常量的命名: 在 Python 中,常量通常使用所有大写字母和下划线命名,例如:

          

1 MY_CONSTANT = 3.14

     8. 私有变量和函数的命名:在 Python 中,私有变量和函数的命名通常以一个下划线作为前缀,例如:

  

1 class MyClass:
2     def __init__(self):
3         self._my_private_variable = 42
4 
5     def _my_private_function(self):
6         pass

但需要注意的是,这并不是真正的私有,而只是一种约定。任何变量和函数都可以从外部访问,因为 Python 没有真正的私有性。

 

 

4. python的数据类型

Python 是一种动态类型语言,提供了多种内置的数据类型。以下是 Python 的全部数据类型:

1. 整型 (int)

int 是一种表示整数的数据类型,可以是正数、负数或零。在 Python 中,整数没有长度限制。

1 x = 10
2 y = -5

2. 长整型 (long)

在 Python 2 版本中,long 是一种表示任意大整数的数据类型。在 Python 3 版本中,int 本身就可以表示任意大整数,long 已经被弃用

3. 浮点型 (float)

float 是一种表示带小数点的实数的数据类型。在 Python 中,float 类型的数值可以使用科学计数法表示。

1 x = 3.1415
2 y = 1.0e-5

4. 复数型 (complex)

complex 是一种表示复数的数据类型,具有实部和虚部。在 Python 中,实部和虚部均为浮点型数值。

1 x = 3 + 4j
2 print(x)  # 输出:(3+4j)
4 y = complex(2,-3)
5 print(y)  # 输出:(2-3j)
7 y = complex(2,4)
8 print(y)  # 输出:(2+4j)

5. 布尔型 (bool)

bool 是一种表示逻辑值 (True 或 False) 的数据类型。在 Python 中,在条件语句、循环和其他操作中使用 bool 值非常常见。

1 x = True
2 y = False

6. 字符串型 (str)

str 是一种表示字符序列的数据类型,可以使用单引号、双引号或者三引号来表示。在 Python 中,字符串提供了一系列的方法来操作字符串数据。

1 x = 'hello'
2 y = "world"
3 z = """this is a
4 multi-line string"""

7. 列表 (list)

list 是一种有序、可变类型的容器,可以包含任何类型的元素。在 Python 中,列表提供了一系列的方法和操作来修改和查询列表数据。

1 x = [1, 2, 3, 4, 5]
2 y = ['apple', 'banana', 'cherry']

 

8. 元组 (tuple)

tuple 是一种有序、不可变类型的容器,可以包含任何类型的元素。在 Python 中,元组也提供了一些方法和操作来查询元组数据。

1 x = (1, 2, 3, 4, 5)
2 y = ('apple', 'banana', 'cherry')

9. 集合 (set)

set 是一种无序、可变类型的容器,不能包含重复的元素。在 Python 中,集合提供了一系列的方法和操作来查找、添加、删除和修改集合数据。

1 x = {1, 2, 3, 4, 5}
2 y = {'apple', 'banana', 'cherry'}

10. 字典 (dict)

dict 是一种无序、可变类型的容器,包含键值对。在 Python 中,字典提供了一些方法和操作来添加、查询和修改字典数据。

1 x = {'name': 'Alice', 'age': 25, 'email': 'alice@example.com'}
2 y = {1: 'apple', 2: 'banana', 3: 'cherry'}

11. None

在 Python 中,None 是一种单独的数据类型,表示缺失或无值。它通常被用作函数的返回值或作为变量的默认值。虽然它表示缺失或无值,但它本身是一个有效的 Python 对象。因此,可以把 None 看作一种数据类型,但它是一种特殊的数据类型。也可以说,它是一种空类型,因为它不包含任何有意义的值。

1 x = None
2 print(x)  # 输出:None

 

12. 其他

python一切皆是对象,比如函数,不仅仅是一种对象,还是一种数据类型。我们可以把函数赋值给变量,并且可以把函数作为参数传递给其他函数,从而实现函数式编程的思想。

在 Python 中,通过 def 关键字定义的函数被称为用户自定义函数,也可以使用内置函数来创建函数对象。例如,可以使用 lambda 表达式创建匿名函数,并且可以把匿名函数赋值给变量或者传递给其他函数。

由于函数是一种数据类型,所以可以方便地执行很多与函数相关的操作。例如,可以使用 dir() 函数查看函数的属性和方法;可以使用 help() 函数查看函数的帮助文档;可以使用 callable() 函数来检查一个对象是否为可调用对象 (函数)。

可以使用内置函数 compile()exec() 和 eval() 来创建函数对象。这三个函数都是用于执行动态代码的函数,它们可以接受字符串类型的代码作为参数,并编译、执行或求值运行这段代码。因此,这三个函数都可以用于创建函数对象。

具体来说:

  • compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1):将指定的 ASCII 字符串编译为代码对象,并返回该对象。如果要将编译后的代码转换为函数对象,可以通过 types.FunctionType() 将其转换。其中,source 参数是要编译的源码字符串,filename 参数可以是字符串,表示代码的文件名,mode 参数可以是字符串,表示编译的模式,可选值为 'exec'、'eval' 和 'single',默认为 'exec'。其他参数一般不需要设置。例如,下面的代码演示了如何使用 compile() 创建一个函数对象,并调用该函数:
1 code = 'def hello():\n    print("Hello, world!")'
2 compiled_code = compile(code, '<string>', 'exec')
3 exec(compiled_code)
4 hello()  # pyCharm会报错,但运行正常。输出:Hello, world!
  • exec(source, globals=None, locals=None):将指定的 ASCII 字符串作为 Python 程序执行,并返回 None。如果要将执行的代码转换为函数对象,可以先使用 compile() 函数编译成代码对象,再使用 types.FunctionType() 将其转换。其中,source 参数是要执行的源码字符串,globals 和 locals 参数分别是全局和局部命名空间。例如,下面的代码演示了如何使用 exec() 创建一个函数对象,并调用该函数:
1 code = 'def hello():\n    print("Hello, world!")'
2 exec(code)
3 hello()  # pyCharm会报错,但运行正常。输出:Hello, world!
  • eval(expression, globals=None, locals=None):求解指定的表达式,并返回该表达式的运算结果。如果表达式是一个函数定义,可以先使用 compile() 编译成代码对象,再使用 types.FunctionType() 将其转换为函数对象。例如,下面的代码演示了如何使用 eval() 创建一个函数对象,并调用该函数:
1 code = 'lambda x, y: x + y'
2 add = eval(code)
3 print(add(1, 2))  # 输出:3

 

5. 变量的语法

通过赋值操作符 = 来定义变量。具体来说,变量定义语法如下:

变量名 = 值

1. 变量名 必须符合 Python 的标识符规定级命名规范

2.值 是要赋给变量的值,可以是任何合法的 Python 表达式,例如数值、字符串、列表、元组、字典、函数等等。

3. 变量在使用前必须先定义。如果在使用变量之前未定义,Python 解释器将会抛出 NameError 异常。

复制代码
print(name)
# 没有定义name会报如下错
# Traceback (most recent call last):
# File "<pyshell#36>", line 1, in <module>
#     print(name)
# NameError: name 'name' is not defined

name
# 直接在idle shell输出变量名,会报如下错
# Traceback (most recent call last): # File "<pyshell#37>", line 1, in <module> # name # NameError: name 'name' is not defined
复制代码

 

4. 多重赋值语法即同时为多个变量赋值

x, y, z = 1, 2, 3
print(x,y,z)  # 输出: 1 2 3

5. 链式赋值语法在一行中为多个变量赋相同的值

x = y = z = 0

 

6. 变量的分类及其作用域

按照变量的作用域分为:全局变量、局部变量、类变量、实例变量、方法变量

6.1 全局变量

作用域为整个程序(整个程序是说的一个模块)。如果想在函数体、方法体内修改全局变量的值,需要使用global 关键字

6.2 局部变量

只在定义变量的函数或语句块内有效。函数内部的变量使用有两种方式:一种是函数的参数,一种是函数内部定义的变量。这些变量都是局部变量,函数执行完毕后就会自动销毁。

6.3 类变量也叫成员变量

类定义中定义的变量,它是类的一部分,在类中可以定义和使用,被所有类的实例共享类变量。类变量可以被类或者类的实例访问和修改。

6.4 方法变量

是类和类的实例的一部分,只在方法的作用域内生效,方法的参数也是方法变量的一部分。方法变量的生命周期与方法相同,在执行完方法后就会自动销毁。

6.5 实例变量

实例变量定义语法:实例.变量名=变量值

实例变量修改:实例.变量名=变量值 

实例变量访问:实例.变量名

复制代码

# 全局变量
global_var = 10


# 局部变量
def my_func(arg1, arg2):
local_var = 20
print(arg1 + arg2 + local_var)


# 类变量
class MyClass:
class_var = 30

def __init__(self):
self.instance_var = 40


# 方法变量
class MyClass2:
def my_method(self, arg1, arg2):
method_var = 50
print(arg1 + arg2 + method_var)
global global_var # global global_var = 20 此种写法是错误的
global_var = 20 # 在方法内访问或修改全局变量
print(global_var) # 输出20
print(self.instance_var_2) # 输出:我也是实例变量


# 使用
my_func(1, 2) # 输出: 23

print(MyClass.class_var) # 输出: 30

a = MyClass()
print(a.class_var) # 输出: 30
print(a.instance_var) # 输出: 40

b = MyClass()
print(b.class_var) # 输出: 30
print(b.instance_var) # 输出: 40

print()

c = MyClass2()
c.instance_var_2 = "我也是实例变量"
c.my_method(3, 4) # 输出: 57

print(global_var) # 输出: 20
 
复制代码

其中,global_var 是全局变量,local_var 是局部变量,class_var 是类变量,instance_var 是实例变量,arg1 和 arg2 是方法变量。全局变量可以在程序的任何地方被访问和修改,局部变量只在函数内部有效,实例变量只能通过实例进行访问,而不同实例中的实例变量是不相同的,类变量在类的所有实例中共享。方法变量只在方法的作用域内有效,对于类和实例来说都是一样的。

7. 变量的内存模型

Python 中的变量和其他编程语言中的变量有些不同,它是一种引用类型的变量。在 Python 中,每个变量都是一个对象的引用,而不是传统意义上的变量。这意味着变量在使用前必须赋值,否则会抛出异常。

在 Python 中,变量有以下特点:

  1. 变量的赋值会创建对象,并将对象的引用赋值给变量,如果已经存在相同值的对象,就将变量指向现有对象的引用。
  2. 变量的删除只有在没有对象引用变量时才会释放内存。
  3. 变量的值可以是数字、列表、元组、字典等各种数据类型。
  4. 变量的值可以是函数或类等对象,即变量可以指向函数或类,它们就可以像变量一样进行操作、传递和使用。

Python 中变量的内存模型是基于对象引用的,当有变量引用对象时就会创建一个对象,并返回对象的引用。Python 中有一个内存管理模块 gc,用于自动回收没用到的内存空间,这个模块的实现是基于标记和清理的原理。它通过标记处理机制,把对象分为可达对象和不可达对象。如果一个对象没有被任何引用所指向,就会被当做垃圾进行回收,这样就可以释放内存空间了。

复制代码
 1 a = 10   # 创建整数对象并将引用赋值给变量 a
 2 b = a    # 变量 b 也引用整数对象
 3 c = a    # 变量 c 也引用整数对象
 4 
 5 '''
 6 从输出结果a、b、c的id值一样,说明变量a、b、c引用同一个对象(10)
 7 '''
 8 print(id(a))  # 140705379382344
 9 print(id(b))  # 140705379382344
10 print(id(c))  # 140705379382344
11 
12 '''
13 修改变量a的值,此时a变量的id值就发生了变化,但b、c变量的值没有变化
14 '''
15 a = 20   # 创建新的整数对象并将引用赋值给变量 a
16 print(id(a))  # 140705379382664
17 print(id(b))  # 140705379382344
18 print(id(c))  # 140705379382344
复制代码

Python 的内存模型可以分为三个主要部分:命名空间、对象和引用

  • 命名空间:是一种将名称和对象关联在一起的系统,储存了变量名和对应的变量值之间的关系。Python 运行环境中有多个命名空间,例如内置命名空间、全局命名空间和局部命名空间等等。

  • 对象:是指存储数据的内容,Python 中数据都以对象的形式存在。每个对象都有一个唯一的标识符、类型和值,标识符是一个整数,通过 id() 函数获取;类型是对象的数据类型,可以通过 type() 函数获取;值是对象存储的具体数据。

  • 引用:是指在 Python 中访问、操作对象的一个标识,可以看作是指向对象内存地址的指针。变量实际上存储的是对象的引用,而不是对象本身。可以使用 id() 函数获取变量的引用地址。

 

8. 变量作用域链详解及示例

Python 中的作用域链搜索顺序决定了变量的访问顺序。当程序在一个函数中引用某个变量时,Python 会按照下面的顺序从当前作用域开始搜索该变量:

  1. 当前函数的局部作用域。
  2. 外层嵌套函数的局部作用域(如果有的话,也叫闭包作用域)。
  3. 全局作用域:是指在一个模块中定义的变量和函数名称。在 Python 中,每个模块都有自己的全局命名空间,也就是说在每个模块中定义的变量和函数,只在该模块内部任何地方都是可见和可用的。
  4. 内置作用域:Python 预定义的常用函数和变量都在内置作用域中。

闭包作用域:在函数内部定义函数并返回,内部函数可以访问外部函数的变量,这个作用域就是闭包作用域。

对于每一个作用域,它会先搜索局部作用域,如果没有找到需要的变量,就会向外层作用域继续搜索,直到找到为止。如果所有的作用域都搜索完了还没有找到该变量,就会抛出 NameError 异常。

示例1:局部作用域中的变量

1 def my_func():
2     x = 10  # 局部变量
3     print(x)
4 
5 my_func()  # 输出 10

在这个例子中,变量 x 是在函数内部定义的,因此它属于函数的局部作用域。因此,当我们尝试输出 x 的值时,Python 会先从局部作用域开始搜索,找到变量 x 并输出其值为 10。

 

示例2:全局作用域中的变量

1 x = 10  # 全局变量
2 
3 def my_func():
4     print(x)
5 
6 my_func()  # 输出 10

在这个例子中,变量 x 是在函数外面定义的,因此它属于全局作用域。当我们尝试输出 x 的值时,Python 会先从函数内部的局部作用域开始搜索,但是在局部作用域中找不到变量 x。因此,Python 向外层作用域(也就是全局作用域)发起搜索,找到变量 x 并输出其值为 10

 

示例3:全局作用域和局部作用域

1 x = 10  # 全局作用域
2 
3 def foo():
4     x = 5  # 局部作用域
5     print(x)
6 
7 foo()  # 输出 5
8 print(x)  # 输出 10

述代码中,x 变量在顶层作为全局变量进行定义,foo() 函数内部的 x 变量则属于局部作用域。在函数内部访问变量 x 时,首先会在函数内部搜索局部作用域,然后是全局作用域,因此最终输出的是局部变量 x 的值 5。

 

示例4:嵌套作用域中的变量

复制代码
1 def outer_func():
2     x = 10  # 嵌套变量
3     
4     def inner_func():
5         print(x)
6     
7     inner_func()
8 
9 outer_func()  # 输出 10
复制代码

在这个例子中,我们定义了两个函数 outer_func() 和 inner_func(),并在 outer_func() 中定义了变量 x。当我们在 inner_func() 中引用变量 x 时,Python 会先从 inner_func() 的局部作用域开始搜索,但在局部作用域中找不到变量 x。因此,Python 向外层作用域(也就是 outer_func() 的局部作用域)发起搜索,找到变量 x 并输出其值为 10。

 

示例5:闭包作用域

复制代码
 1 def outer():
 2     x = 10  # 闭包作用域
 3 
 4     def inner():
 5         print(x)
 6     
 7     return inner
 8 
 9 x = 20  # 全局作用域
10 foo = outer()
11 foo()  # 输出 10
复制代码

上述代码中,outer() 函数定义内部的 x 变量属于闭包作用域,它可以被 outer() 函数内部定义的 inner() 函数所访问。当 outer() 函数返回 inner() 函数时,它将 inner() 函数和闭包作用域一起返回。在全局作用域中创建变量 x 的值为 20,然后调用 foo() 函数,输出闭包作用域中的变量值 10。

 

示例6:函数参数的作用域

1 def my_func(x):
2     print(x)
3 
4 my_func(10)   # 输出 10

在这个例子中,我们定义了一个函数 my_func(),其参数为 x。当我们在 my_func() 中引用参数 x 时,Python 会优先从 my_func() 的局部作用域开始搜索,找到参数 x 并输出其值为 10。

 

posted @   Allen_Hao  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示