Python进阶之旅:深入理解变量作用域、垃圾回收、拷贝机制与异常处理

简介: Python进阶之旅:深入理解变量作用域、垃圾回收、拷贝机制与异常处理

前言

    在Python编程的进阶道路上,理解变量作用域、垃圾回收、拷贝机制与异常处理至关重要。本文将深入探讨这些核心概念,助你编写更健壮、高效的代码。从变量作用域到内存管理,再到数据拷贝与异常捕获,让我们一同揭开Python编程的深层奥秘。


一、变量的作用域

1.命名空间

内置命名空间 — python解释器范围下

全局命名空间 — py文件下

局部命名空间 — 函数或类下

2.作用域

内置作用域    校长 
全局作用域    年级主任
嵌套作用域    班主任
局部作用域    讲师
# 全局作用域下的变量:全局变量
a = 10
def func():
    # 嵌套作用域下的变量
    c = 30
    def func1():
        # 局部作用域下的变量:局部变量
        b = 20
def、class、lambda 是可以引入新作用域的

3.LEGB法则

LEGB:作用域的查询顺序(就近原则)
内置作用域     built-in    B
全局作用域     Global      G
嵌套作用域     Enclosed    E
局部作用域     Local       L
局部-->嵌套-->全局-->内置
# 全局作用域下的变量:全局变量
a = 10
def func():
    # 嵌套作用域下的变量
    a = 30
    def func1():
        # 局部作用域下的变量:局部变量
        a = 20
        print(a)
    func1()
func()

4.修改全局变量

a = 10
def func():
    # 修改全局变量的值--》不可变数据类型
    # global 要修改的全局变量的变量名
    # 换行对变量进行重新赋值
    global a
    a = 20
    print(a)
func()
print(a)

5.修改嵌套作用域下的变量

def outer():
    a = 10
    def inner():
        # 修改嵌套作用域下的变量  nonlocal
        # nonlocal 要修改的嵌套作用域下的变量名
        # 换行给变量重新赋值
        nonlocal a
        a += 1
        print(a)
    inner()
    print(a)
outer()

二、python垃圾回收机制

1. 引用计数

每一个对象会维护一个ob_ref表,表中存放当前对象的被引用次数;
当对象的被引用次数为0,当前对象会被作为垃圾进行收回
import sys
# 引用计数
# 获取对象的被引用次数
print(sys.getrefcount(1))
# 引用计数+1
a = 1
b = a
lst = [1,2,3,4]
# 引用计数-1
b = 2
del a
print(sys.getrefcount(1))

2. 标记清除

跟其名称一样,该算法在进行垃圾回收时分成了两步,分别是:
- A)标记阶段,遍历所有的对象,如果是可达的(reachable),也就是还有对象引用它,那么就标记该对象为可达;
- B)清除阶段,再次遍历对象,如果发现某个对象没有标记为可达,则就将其回收。
缺陷:在执行标记清除过程中,会将其他正在执行的程序进行终止。会使得资源利用率极低

3.分代回收

它将内存中的对象按生存期划分为几个不同的"代",每次只对某一代进行回收,
优点:减少垃圾回收的次数,提高垃圾回收的效率。
它将内存中的对象分为三种:新生代、老年代和永久代。
  新生代只包括新创建的对象;
  老年代是存放比较“老”的对象,也就是存活比较久的对象;
  永久代则存放三种物件:模块、类和常量。

三、深浅拷贝

1. is 和 ==

# is和 ==
# a == b:判断a和b的值是否相等;如果相等则返回True,否则返回False
# a is b:判断a和b是否是同一个数据;
# 获取对象的内容地址   id(数据)
# 指向关系:整型、浮点型、字符串、元组   (不可变)
a = {"name":"张三"}
b = {"name":"张三"}
print(id(a))
print(id(b))
print(a == b)
print(a is b)

2.浅拷贝

import copy
# 拷贝模块  copy
# 浅拷贝  需要使用copy模块中copy方法
# 结论:浅拷贝只拷贝第一层,深层次的数据改变都会影响其他.
# 拷贝不可变数据类型的数据--》不可变数据类型永远指向关系
a = (1,2,3)
b = copy.copy(a)
print(id(a),id(b))
print(a is b)
# 拷贝可变数据类型的数据
list1 = [1,2,3,[4,5,6]]
list2 = copy.copy(list1)
# 获取整个数据的id,浅拷贝后的数据id不同
print(id(list1),id(list2))
print(list1 is list2)
# 查询拷贝前后深层次数据是否是同一个
print(id(list1[3]),id(list2[3]))
print(list1[3] is list2[3])
# 修改原数据中浅层数据,拷贝后的数据不会发生变化
list1.append(7)
print(list1)
print(list2)
# 修改原数据中深层数据,拷贝后的数据会随之发生变化
list1[3].append(8)
print(list1)
print(list2)

3.深拷贝

import copy
# 深拷贝  需要使用copy模块deepcopy
# 结论:深拷贝是完全拷贝,数据变化只影响自己本身
# 拷贝不可变数据类型--》不可变数据类型永远都是指向关系
a = ("hello",)
b = copy.deepcopy(a)
print(id(a),id(b))
print(a is b)
# 拷贝可变数据类型
list1 = [1,2,3,[4,5,6]]
list2 = copy.deepcopy(list1)
# 获取整个数据的id,拷贝后的数据id不同
print(id(list1),id(list2))
print(list1 is list2)
# 查询拷贝前后深层次数据是同一个
print(id(list1[3]),id(list2[3]))
print(list1[3] is list2[3])
# 对原数据的浅层数据进行操作,拷贝后的数据不会发生变化
list1.append(7)
print(list1)
print(list2)
# 对原数据的深层数据进行操作,拷贝后数据不会发生变化
list1[3].append(8)
print(list1)
print(list2)

4.深浅拷贝的区别

浅拷贝:只拷贝第一层数据,深层数据还是指向关系

深拷贝:完全拷贝,拷贝前后的数据没有关系


四、异常处理

1.简单异常处理

# 简单异常处理
# try:
#     存放可能会出现问题的代码
# except 异常类型:
#     如果真的出现这个异常,则执行except中的代码
list1 = [1,2,3]
try:
    print(list1[20])
except IndexError:
    print("好好数数你的索引!!!!")

2.处理多种异常

2.1 第一种方式

# try:
#     存放可能会出现问题的代码
# except 异常类型:
#     如果真的出现这个异常,则执行except中的代码
# except 异常类型:
#     如果真的出现这个异常,则执行except中的代码
list1 = [1,2,3]
try:
    print(list2[20])
except IndexError:
    print("好好数数你的索引!!!!")
except NameError:
    print("瞧瞧你的变量名~")

2.2 第二种方法

# try:
#     存放可能会出现问题的代码
# except (异常类型1,异常类型2):
#     如果真的出现这个异常,则执行except中的代码
list1 = [1,2,3]
try:
    print(list1[20])
except (IndexError,NameError):
    print("好好看看你的变量")

2.3 第三种方式

# try:
#     存放可能会出现问题的代码
# except:
#     如果真的出现异常,则执行except中的代码
list1 = [1,2,3]
try:
    list1.add(4)
    print(list2[20])
except:
    print("好好看看你的变量")

3.获取异常信息

3.1 单个异常

# 获取错误信息
# 异常类型 as 变量:将出现当前异常的错误信息赋值给变量
list1 = [1,2,3]
try:
    print(list1[20])
except IndexError as e:
    print(e)

3.2 多个异常

# 获取错误信息
# 异常类型 as 变量:将出现当前异常的错误信息赋值给变量
list1 = [1,2,3]
try:
    print(list1[20])
except (IndexError,NameError) as e:
    print(e)

4.万能异常处理

# Exception:所有常规异常的基类,包含所有的常规异常
# try:
#     存放可能会出现问题的代码
# except Exception as e:
#     print(e)   
#     如果真的出现异常,则执行except中的代码;e接收所有的错误信息
list1 = [1,2,3]
try:
    list1.add(4)
    print(list1[20])
except Exception as e:
    print(e)

5.else

# try:
#     可能会出现问题的代码
# except Exception as e:
#     如果真的出现异常则执行except中的代码块
# else:
#     如果代码没有出现异常则执行else中的代码块
list1 = [1,2,3]
try:
    print(list1[20])
except Exception as e:
    print(e)
else:
    print("嘿嘿嘿嘿嘿嘿")

6.finally

# finally-->可以只与try搭配使用
# try:
#     可能会出现问题的代码
# except Exception as e:
#     如果代码出现问题则执行except中的代码块
# else:
#     如果代码没有问题则执行else中的代码块
# finally:
#     无论代码是否出现问题最终都会执行finally中的代码块
list1 = [1,2,3]
try:
    print(list1[2])
except Exception as e:
    print(e)
    print("这是except中的代码")
else:
    print("这是else中的代码")
finally:
    print("这是finally中的代码")

7.自定义异常

class MyCls:
    def __init__(self,s):
        self.s = s
    def a(self,a,b):
        try:
            return a/b
        except Exception as e:
            if self.s == True:
                print(e)
            else:
                # 将原本需要抛出的异常进行抛出
                # raise 异常类型  -->在程序中raise 后面的异常类型可以不指定
                raise
my = MyCls(True)
print(my.a(10,0))


相关文章
|
30天前
|
存储 Python
在Python中,什么是作用域
【10月更文挑战第12天】在Python中,什么是作用域
15 2
|
2月前
|
Python
关于 Python 列表解析式的作用域问题
关于 Python 列表解析式的作用域问题
56 11
|
1月前
|
存储 自然语言处理 Python
解密 Python 的作用域和名字空间
解密 Python 的作用域和名字空间
15 1
|
2月前
|
缓存 Java Python
python垃圾回收&缓存机制
python垃圾回收&缓存机制
|
2月前
|
存储 算法 Java
关于python3的一些理解(装饰器、垃圾回收、进程线程协程、全局解释器锁等)
该文章深入探讨了Python3中的多个重要概念,包括装饰器的工作原理、垃圾回收机制、进程与线程的区别及全局解释器锁(GIL)的影响等,并提供了详细的解释与示例代码。
28 0
|
3月前
|
Python
Python变量的作用域_参数类型_传递过程内存分析
理解Python中的变量作用域、参数类型和参数传递过程,对于编写高效和健壮的代码至关重要。正确的应用这些概念,有助于避免程序中的错误和内存泄漏。通过实践和经验积累,可以更好地理解Python的内存模型,并编写出更优质的代码。
31 2
|
3月前
|
算法 Java 开发者
Python垃圾回收机制
Python垃圾回收机制
|
4月前
|
数据采集 网络协议 数据挖掘
网络爬虫进阶之路:深入理解HTTP协议,用Python urllib解锁新技能
【7月更文挑战第30天】网络爬虫是数据分析和信息聚合的关键工具。深入理解HTTP协议及掌握Python的urllib库对于高效爬虫开发至关重要。HTTP协议采用请求/响应模型,具有无状态性、支持多种请求方法和内容协商等特点。
51 3
|
4月前
|
网络协议 Python
网络世界的建筑师:Python Socket编程基础与进阶,构建你的网络帝国!
【7月更文挑战第26天】在网络的数字宇宙中,Python Socket编程是开启网络世界大门的钥匙。本指南将引领你从基础到实战,成为网络世界的建筑师。
64 2
|
4月前
|
SQL 安全 Go
SQL注入不可怕,XSS也不难防!Python Web安全进阶教程,让你安心做开发!
【7月更文挑战第26天】在 Web 开发中, SQL 注入与 XSS 攻击常令人担忧, 但掌握正确防御策略可化解风险. 对抗 SQL 注入的核心是避免直接拼接用户输入至 SQL 语句. 使用 Python 的参数化查询 (如 sqlite3 库) 和 ORM 框架 (如 Django, SQLAlchemy) 可有效防范. 防范 XSS 攻击需严格过滤及转义用户输入. 利用 Django 模板引擎自动转义功能, 或手动转义及设置内容安全策略 (CSP) 来增强防护. 掌握这些技巧, 让你在 Python Web 开发中更加安心. 安全是个持续学习的过程, 不断提升才能有效保护应用.
54 1