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