python基础之内存管理与用户交互
用户交互
1.接收用户输入(在python3中input:用户输入任何值,都存成字符串类型。在python2中input:用户输入什么类型,就存成什么类型raw_input:等于python3的input)
name= input("请输入......:")
print(name)
代码注释分单行和多行注释, 单行注释用#,多行注释可以用三对双引号""" """ 代码注释的原则: 1. 不用全部加注释,只需要在自己觉得重要或不好理解的部分加注释即可 2. 注释可以用中文或英文,但不要用拼音
!/usr/bin/env python
-*- coding: utf-8 -*-
2.输入输出
在了解格式化输出前,我们应了解输入输出。编程是用来完成人与机器的交互的,交互必然要有信息的传递,也就是输入和输出。
print() :括号里加上要输出的内容,如字符串,数字,或者一个变量名,就可以向屏幕输出内容。 print("张三") # 张三 print(18) # 18 name = "lalal" print(name) # lalal input() :可以向程序输入内容,内容默认是字符串的格式. age = input() age = input("请输入年龄:") 当执行完第一行代码后,程序就在等待你的输入,你可以输入任意字符,然后回车完成。但通常我们像第二行代码一样,在input()的括号里加一些提示性的字符,便于交互。 input输入默认是字符串型的,如果需要修改,可以人为的声明。 age = int(input("请输入年龄")) # 这样能得到一个int型变量。
注意:
python2中提供了两种输入方法
I.raw_input(),其用法和python3的 input() 完全相同
II.input() ,其要求用户必须明确声明输入的数据类型(数字除外),输入什么类型就存成什么类型
so,在使用python2的程序时,先要掌握python的数据类型,这对用户是很不友好的。
3.格式化输出
如果有两个变量:name = "lalal" ,city = "上海" ,想要输出“我的名字是lalal,我来自上海”,你可能会想到这样的代码:
name = "lalal"
city = "上海"
print("我的名字是",name,"我来自",city)
但如果变量很多,这样写既不易读,也不利于编程。所以我们选择使用格式化输出。用%s、%d等占位符占位,在行末放置要输出的内容。
name = "lalal"
city = "上海"
print("我的名字是%s,我来自%s" % (name, city))
因为要输出两个变量,所以要把两个变量用括号写成元组(一种数据类型)的形式。%s是通用的,不管name、city是什么类型都可以用%s占位,还有一些占位符如 %d,只能表述整形数据,%f只能表示浮点型数据。
Cpython解释器的内存管理
当程序中引用一个变量时,创建了变量值的内存空间,当不需要使用该变量时,如果不采取任何措施,变量会一直占用内存,这时,Cpython解释器提供了一个垃圾回收机制:
垃圾:当一个值没有绑定任何变量名(该值的引用计数=0)时,该值就是一个垃圾 引用计数增加 age=18 # 18的引用计数等于1 x=age # 18的引用计数等于2 print(age) print(x) # 引用计数减少 age=19 # 18的引用计数等于1 print(age) del x # 18的引用计数等于0
当变量被引用一次,引用计数+1,变量的引用计数为0时,就没有变量名可以访问到这个值了,解释器就会将其回收,以节省内存。
然而,为了方便使用,Cpython解释器还提供了一个小整数池,里面包含了-5——256 之间的整数,启动解释器时,这些数字会直接在内存中创建空间,随时可以使用。
1、在交互式模式下 Python实现int的时候有个小整数池。为了避免因创建相同的值而重复申请内存空间所带来的效率问题, Python解释器会在启动时创建出小整数池,范围是[-5,256],该范围内的小整数对象是全局解释器范围内被重复使用,永远不会被GC回收 每创建一个-5到256之间的整数,都是直接从这个池里直接拿走一个值,例如 >>> y=4 >>> id(y) >>> >>> x=3 >>> x+=1 >>> id(x) 在pycharm中 但在pycharm中运行python程序,pycharm出于对性能的考虑,会扩大小整数池的范围,其他的字符串等不可变类型也都包含在内一便采用相同的方式处理了,只需要记住这是一种优化机制,至于范围到底多大,无需细究
x=1234 # import sys # print(sys.getsizeof(x)) # 28,取内存字节 # # y=x # print(sys.getrefcount(x)) # 5,通过参数引用目标对象,也会增加计数 def test(z): # 定义一个形参 print(x is z) # 引用传递,x和z此时指向同一对象 test(x) # 实参 # True 实参x的内容传给了形参z # 将对象的多个名字中的某个重新赋值(或者说关联到其他的对象),不会影响其他的名字 # 只有对名字赋值才会变更引用关系,即通过名字引用修改了对象自身,而并未重新关联其他对象
弱引用
(int\tuple\str\list 等不支持)
保留引用,不增加计数,不阻止目标被收回
import weakref,sys class X: pass a=X() w=weakref.ref(a) print(w() is a) # True print(sys.getrefcount(a)) # 不会增加引用计数
缓存、监控、实现Finalizer(在对象被回收时执行额外的清理操作)
gc.disable() 关闭gc
gc.enable() 重新启动gc
gc.collect() 主动启动一次回收操作,循环引用对象被正确回收