python中内存管理等10个编码习惯

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 【7月更文挑战第3天】本文涵盖了Python编程中的变量管理、模块导入、命令行参数、内存管理和面向对象设计的10个关键概念。

简介

本文要点涵盖了Python编程中的变量管理、模块导入、命令行参数、内存管理和面向对象设计的一些关键概念:

  1. 避免在函数参数中使用可变数据结构,如列表,
  2. 防止模块循环导入,模块间应明确依赖关系以保护导入。
  3. 命令行参数-u无缓冲输出,-m以模块执行,-x忽略第一行,-X设置特定选项,-从stdin读取。
  4. Python缓存小整数和短字符串is检查对象标识,==检查值相等。
  5. 内存管理基于引用计数和垃圾回收。sys.getrefcount()查看计数,但会因调用本身+1。
  6. 自动垃圾回收可通过gc模块手动触发。阈值可通过gc.get_threshold()查看和设置。
  7. 分代策略:对象按生存时间分代,更老的对象更不易被视为垃圾。垃圾回收针对不同代有不同的触发条件。
  8. 引用环可能导致垃圾回收难题,Python使用额外的引用计数(gc_ref)来检测和回收这类循环引用。
  9. 迭代器、生成器__iter__定义可迭代对象,__next__创建迭代器,yield用于生成器,提供惰性计算。
  10. 抽象方法:使用@abc.abstractmethod声明必须由子类实现的方法,配合__metaclass__ = abc.ABCMeta确保子类覆盖。

mandala曼德罗符号.png

1,不要在函数的参数使用可变数据结构:

注意在函数变量不要使用它

def foo(x=[]):
    x.append(1)
    print(x)

>>>foo()
[1]

>>>foo()
[1,1]

>>>foo()

[1,1,1]

def foo(p=None):
    if p is None:
        p = []
    p.append(1)
    print(p)

foo()
[1]
foo([2,3,4])
[2,3,4,1]

典型数据结构

image.png

2 避免模块的循环导入

我们定义一个老王模块,再定义一个小李模块,相互导入时,将报错

# laowang.py
import xiaoli
count =4
def main():
    wilma.pr('Hello')
if __name__ == '__main__':
    main()

# xiaoli.py
import laowang
def pr(str):
    print(str*fired.count)
if __name__== '__main__':
    pr("Ok")

导入问题,如果在使用其他语言 比如 shell 脚本引用 python代码时,需要将python项目加入 linux环境变量。 <=python2.7

export PYTON_PATH=$PYTHON_PATH:/xxx/xxx/XXXProject

或者编辑 python虚拟环境,添加 setup.py, 然后执行 python install -e .

3 系统输出基础规则

该次执行不缓存sys.stdout,直接输出控制台

@参数 -u unbuffered

执行时带参数m,以Script方式执行py模块

@参数 -m 

跳过py模块第一行,允许使用非unix形式

@参数 -x

实体具体选项(set implementation-specific option)

@参数 -X

程序读取文件内容并执行

file 

程序从stdin 读取

@参数 -

python3 --help # 显示所有参数

dd

4 小的整数 和短小字符,python将缓存以便重复使用

并且is关键字,用于判断两个引用所指对象是否相同

    >>> a = 'gd'
>>> b = 'gd'
>>> a is b
True

== 只判断值是否相同

    a2 = []
b2 = []
>>> a2 is b2
False
>>> b2 == a2
True

5 内存管理对象引用时python基本构成方式

python 内存回收 基于 引用计数 和 分级回收。

赋值的本质 a=1,实际上时修改globals()字典的值,局部变量值的修改locals()的访问和修改

>>> a1
    very good man
>>> globals()['a1'] = 'bad good mm'
>>> globals()

6 引用对象reference count

sys.getrefcount() 查看对象的引用计数,sys.getrefcount()在查看某个引用时将创建一个临时引用,所以引用计数将多1

    >>> c=[1,2,3]

getrefcount(c) #这里c只有一次引用,但是计数时2,因为当前查询有一次临时引用

   2

引用计数的减少和增加

   >>> d=c

getrefcount(c) # 增加引用d,计数3

     3

del d #删除引用d,c的引用计数又重新为2

7 内存管理中垃圾回收机制 garbage collection

垃圾回收时py 独占进行的,大大降低py效率,特定条件下自动启动垃圾回收。

手工回收 gc.collect()

py 运行时分配对象obj allocation 和取消分配对象 deallocation次数被记录,高于垃圾回收阈值,启动垃圾回收

gc.get_threshold()查看该阈值,gc.set)threshold()重新设置该阈值

(700, 10, 10) 700表示启动垃圾回收阈值,10,10表示分别回收的阈值

8 内存管理中垃圾回收分代策略 generation,

基本假设如下。存活时间越久,越不可能在后面程序中变为垃圾。 这样所有对象分为0,1,2三代,所有新建对象都是0代。某一对象经历垃圾回收,仍然存活,那么它就被归入下一代对象。

垃圾回收时,一定扫描0代对象,如果0代经过一定次数垃圾回收,下一次对0代和1代扫描清理,

当1代也经历一次次数垃圾回收,这启动0,1,2所有对象的扫描

以上gc.get_threshold()返回(700,10,10)两个表示每10次0代垃圾回收,将配置1次1代垃圾回收,每10次1代垃圾回收,才有1次2代垃圾回收。

9 内存管理中两个对象相互引用,

相互引用构成引用环 reference cycle,该引用环将给上一节2.4.1的垃圾回收带来困难,

引用环可能构成一些无法使用但引用计数不为0的对象 为了回收该引用环对象,

py复制了每个对象的引用计数为 gc_ref 遍历所有对象,将每个对象引用的对象相应的gc_ref减1,遍历结束后,

gc_ref不为0的对象和这些对象的引用对象,以及继续更新下游引用对象,被爆了,其他对象被回收。

参考 内存管理,函数默认参数,动态类型

10 迭代器的不同

可迭代对象 iter

迭代器 iter + next

生成器 特殊迭代器 yield

          def yd():
        a = 100
        yield a
        yield a*8
        yield 8000
  • 使用抽象方法 (函数)

    对象方法(self.对象方法),类方法(@classmethod),静态方法(@staticmethod)

    抽象方法 需要子类实现的方法 用@abc.abstractmethod以及 metaclass = abc.ABCMeta
    使得任何继承自父类的子类必须覆盖实现抽象方法,否则抛出异常

目录
相关文章
|
2天前
|
监控 Python
paramiko 模块 ---Python脚本监控当前系统的CPU、内存、根目录、IP地址等信息
paramiko 模块 ---Python脚本监控当前系统的CPU、内存、根目录、IP地址等信息
|
2天前
|
存储 Java Linux
Python----全局变量、内存管理、数据类型
Python----全局变量、内存管理、数据类型
|
2天前
|
算法 Java C++
C++和Python在内存管理上的主要区别是什么?
【7月更文挑战第2天】C++和Python在内存管理上的主要区别是什么?
6 1
|
10天前
|
监控 算法 Java
Python中管理内存
Python中管理内存
|
10天前
|
监控 算法 Java
使用Python的垃圾回收机制来管理内存
使用Python的垃圾回收机制来管理内存
|
16天前
|
自然语言处理 Python
Python编码问题
Python编码问题是指在处理文本时,由于编码不一致导致程序不能正确处理文本的问题。在Python中,编码问题主要有两种情况:文件编码问题和字符串编码问题。
26 7
|
12天前
|
算法 Java 开发者
深入理解Python的内存管理机制
Python 以其简单易学的语法和强大的功能深受开发者欢迎。然而,许多开发者在使用 Python 时并不了解其背后的内存管理机制。本文旨在深入探讨 Python 的内存管理,包括对象的生命周期、引用计数以及垃圾回收机制,从而帮助开发者编写出更加高效和稳定的代码。
|
15天前
|
安全 Java Python
GIL是Python解释器的锁,确保单个进程中字节码执行的串行化,以保护内存管理,但限制了多线程并行性。
【6月更文挑战第20天】GIL是Python解释器的锁,确保单个进程中字节码执行的串行化,以保护内存管理,但限制了多线程并行性。线程池通过预创建线程池来管理资源,减少线程创建销毁开销,提高效率。示例展示了如何使用Python实现一个简单的线程池,用于执行多个耗时任务。
21 6
|
15天前
|
算法 Java 程序员
Python内存管理用引用计数(对象的`ob_refcnt`)跟踪对象,但循环引用(如A-&gt;B-&gt;A)可导致内存泄漏。
【6月更文挑战第20天】Python内存管理用引用计数(对象的`ob_refcnt`)跟踪对象,但循环引用(如A-&gt;B-&gt;A)可导致内存泄漏。为解决此问题,Python使用`gc`模块检测并清理循环引用,可通过`gc.collect()`手动回收。此外,Python结合标记清除和分代回收策略,针对不同生命周期的对象优化垃圾回收效率,确保内存有效释放。
15 3
|
18天前
|
Java 测试技术 开发者
Python中的内存陷阱:如何有效避免内存泄漏
Python开发中,内存泄漏影响性能,垃圾回收机制不总能解决。常见原因包括循环引用、静态变量和大型数据结构未清空。使用`weakref`处理循环引用,避免类属性滥用,及时清理数据结构。利用`gc`模块检测泄漏,启用`with`管理资源,使用弱引用,定期审查和测试代码,遵循内存管理最佳实践。【6月更文挑战第15天】
52 4