python冒号3.6.5版本,学习到类的时候,冒号后面的空格总是报错,我都是而直接使用回车键的,不知道错在何处

悟已往之不谏,知来者之可追
确定要删除当前文章?前三章介绍Python的历史,特性,以及相关编辑器等关系,暂时不考虑研究,如有需要可以参考wiki百科,自行阅读其中一些取自Wiki的资料,可以了解一下我们日常使用比较多的是C版本的Python,也就是用C语言实现的Python解释器,除此之外,还有Java实现的Jython和.net实现的IronPython第四章 Introducing Python Object TypesPython’s Core Data TypesPython 核心数据类型Numbers
5, 999L, 3+4j, DecimalStrings
'spam', "guido's"Lists
[1, [2, 'three'], 4]Dictionaries
{'food': 'spam', 'taste': 'yum'}Tuples
(1,'spam', 4, 'U')Files
myfile = open('eggs', 'r')Other types
Sets, types, None, BooleansPython的动态在于,可以将一个变量指向不同的类型,静态在于调用方法时,必须是指定类型才可以进行调用Number类型,相关的模块Math--提供与Java类似的Java包功能random--随机数,功能比Java使用更方便一些,如random.random(), random.choice([1,3,4,5,6])字符串,简单的sequences of one-character strings 字符链表,可以直接使用下标的方式,访问指定索引的字符,注意Python下不包含char类型[1:3] 链表中所用的切片取值也可以使用* 与+ 来进行字符串的拼接,不过需要注意,字符串是不可修改的,所有的操作将会返回一个新的对象,代表为,s[0]='3' 将会抛出异常在Python中,Number,string,tuples都是不可修改的, list 和dictionaries是可以修改的List,tuples,string中很多方法都是共同拥有的,可以使用dir查看所拥有的属性与方法'''xx''' 用于定义多行字符串,多用于HTML/CSS,以及docStringPython支持使用r和u关键字修饰字符串: 如u'xxx',其中u代表Unicode
r代表2进制流格式,主要是用于忽视/的转义符正则模式匹配使用re模块,需要import如match = re.match('Hello[ \t]*(.*)world', 'Hello Python world')match.group(1)List,可以修改的序列,可以动态的收缩和添加,对对象本身方法的调用将会影响到对象本身使用的时候,需要注意区域检查,防止索引越界,尤其进行添加元素时候,需要使用append方法,移除的话,可以使用pop或者remove方法List中可以随意嵌套其他类型,如List一种比较特殊的List遍历取值方式M=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]col2 = [row[1] for row in M]col2==[2, 5, 8],区域每个元素中的第2个字符串,不知可否多重进行嵌套,不过增加了不少代码复杂度上述需要注意[]的使用,下面加上过滤条件的例子[row[1] for row in M if row[1] % 2 == 0][c * 2 for c in 'spam']
//对结果进行计算Dictionaries 字典, 定义的格式 d={key:value}其中key一般使用字符串表示,value可以为任意的类型可以通过将对象的引用变量 =0,将一个对象回收 //并不确认字典的循环, 使用keys()方法,获取到字典所有的key,然后在循环keys中进行访问Ks = D.keys() for key in Ks:print key, '=&', D[key]在进行循环的时候,可以注意效率的写法&&& squares = []&&& for x in [1, 2, 3, 4, 5]: # This is what a list comp doessquares.append(x ** 2)&&& squares这样只会创建一个List对象使用字典时,也要防止出现key不存在,而导致的访问错误D.has_key('f'),进行判断Tuples,元组 定义方式(), 类似List的数据类型,区别在于值不可修改,而且定义单元素的tuples时,需要注意使用,逗号, 常用于参数传递时,防止被修改Files 类型可以使用内置的open函数,传入方法名+打开方式进行文件的创建f = open('data.txt', 'w')
//w 代表写入,如果不存在将会创建,如果存在将会被覆盖.主要使用close方法进行关闭具体方法可以使用help 与dir进行查看 dir(file)help(file.seek)其他内置类型Sets 集
X = set('spam'),其中包含的内容都是唯一的decimal 小数,代表高精度的小数运算格式Booleans 布尔
包含 False True, 注意首字符大写,转换成int类型时,分别为0,1None类型, 类似Null的存在type(),同样也返回一个特殊的type类型:type(type(False))进行获取.下面复制书上一些章节的问题,都是不错的题目,用空可以复习一下(其实我是为了凑字数)1. Name four of Python’s core data types.2. Why are they called “core” data types?3. What does “immutable” mean, and which three of Python’s core types are considered immutable?4. What does “sequence” mean, and which three types fall into that category?5. What does “mapping” mean, and which core type is a mapping?6. What is “polymorphism,” and why should you care?Quiz Answers1. Numbers, strings, lists, dictionaries, tuples, and files are generally considered tobe the core object (data) types. Sets, types, None, and Booleans are sometimesclassified this way as well. There are multiple number types (integer, long, floatingpoint, and decimal) and two string types (normal and Unicode).2. They are known as “core” types because they are part of the Python languageitself, and
to create other objects, you generally must callfunctions in imported modules. Most of the core types have specific syntax forgenerating the objects: 'spam,' for example, is an expression that makes a stringand determines the set of operations that can be applied to it. Because of this,core types are hardwired into Python’s syntax. In contrast, you must call thebuilt-in open function to create a file object.3. An “immutable” object is an object that cannot be changed after it is created.Numbers, strings, and tuples in Python fall into this category. While you cannotchange an immutable object in-place, you can always make a new one by runningan expression.4. A “sequence” is a positionally ordered collection of objects. Strings, lists, andtuples are all sequences in Python. They share common sequence operations,such as indexing, concatenation, and slicing, but also have type-specific methodcalls.5. The term “mapping” denotes an object that maps keys to associated values.Python’s dictionary is the only mapping type in the core type set. Mappings donot maintain any left-to-right they support access to datastored by key, plus type-specific method calls.
Learning.Python.3rd.Edition 笔记[4]
第四章中很大概的介绍了下Python的core 数据类型,后续章节将会详细介绍个个数据类型
Python支持无限大的数字,不过需要内存支持
Learning.Python.3rd.Edition 笔记[5:7]
The Dynamic Typing Interlude
a = 3的后台操作过程
1. 创建一个对象,将值设置为3.
2. 如果a不存在,则创建一个变量
3. 将变量a指向值为3的这个对象
...
Learning.Python.3rd.Edition 笔记[22-26]章节
Chapter 22
OOP: The Big Picture
Python中class的3个关键特色
2:用户自定义继承(多继承)
3:运算符重载
Python中...
Learning.Python.3rd.Edition 笔记[27-29]
Chapter 27
Exception Basics
本书最后一个Python的主要内容,关于异常处理
与异常相关的关键字
1:try/except
//与Java类似,新特性...
Learning.Python.3rd.Edition 笔记[14:17]
Chapter 15
Function Basics
常用的function操作
myfunc(&spam...
Learning.Python.3rd.Edition 笔记 21章节
Chapter 18
Modules: The Big Picture
Modules Python中最高级别的程序组织单位,包装程序代码和数据用于重用,以文件为单位.
常见的相关关键字有
...
Learning.Python.3rd.Edition 笔记[7:8]
Lists and Dictionaries
链表与字典
List是可以同时包含任意的类型对象的集合,可以使用索引进行访问的有序集合,同时可以任意修改
所包含的内容
Learning.Python.3rd.Edition 笔记[9:14]
Statements and Syntax
声明与语法
Chapter 10
Introducing Python Statements 介绍Python声明
小甲鱼《零基础学习Python》课后笔记(四)
0. 请问以下代码会打印多少次“我爱鱼C!”
while 'C':
print('我爱鱼C!')
会一直打印直到电脑内存被占用完。字符串‘C’是一个非0值,所以whil...
没有更多推荐了,__init__.py内的__all__列表
用来记录此包中有哪些包或模块需要在from import *语句导入时被导入
__all__列表只在from xxx import * 语句中起作用
包的相对导入
是指包内模块的相互导入
from 相对路径包或模块import * 属性或模块
from 相对路径包或模块import *
包的相对导入不能用于import xxx语句中
. 代表当前路径
.. 代表上一级目录
... 代表上二级目录
.... 以此类推
注:相对导入时不能超出包的外部
包的加载路径:
同模块的加载路径搜索
1.搜索当前路径
2.搜索sys.path给定的路径
异常(基础)exception
什么是错误
错误是指由于逻辑或语法等导致一个程序无法正常执行的问题
有些错误是无法预知的
什么是异常
异常是程序出错时标识的一种状态
当异常发生时,程序不会再向下执行,
而转去调用此函数的地方待处理此错误并恢复为正常状态
用作信号,通知上层调用者有错误需要处理
两种语法:
try-except 语句
try-finally语句
try-except 语句语法
可能触发异常的语句
except 错误类型1 [as 变量1]:
异常处理语句1
except 错误类型2 [as 变量2]:
异常处理语句2
except (错误类型3,错误类型4) [as 变量3]:
异常处理语句3
异常处理语句other
未发生异常语句
尝试捕获异常,将程序转为正常状态并继续执行
# 此示例示意 try-except语句的用法
def div_apple(n):
print("%d个苹果您想分给几个人?" % n)
s = input("请输入人数: ")
cnt = int(s)
# &--此处可能触发ValueError类型的错误
result = n / cnt
# &-- 此处可能会触发ZeroDivisionError类型的错误
print("每个人分了%d个苹果" % result)
div_apple(10)
# 此函数可能会触发错误,分苹果失败
print("分完苹果")
except ValueError:
print("分苹果失败,程序已捕获通知并转为正常状态")
except ZeroDivisionError:
print("没有人来,那苹果就拿来回吧!")
print("程序正常退出")
# 此示例示意 try-except语句的用法
def div_apple(n):
print("%d个苹果您想分给几个人?" % n)
s = input("请输入人数: ")
cnt = int(s)
# &--此处可能触发ValueError类型的错误
result = n / cnt
# &-- 此处可能会触发ZeroDivisionError类型的错误
print("每个人分了%d个苹果" % result)
div_apple(10)
# 此函数可能会触发错误,分苹果失败
print("分完苹果")
except (ValueError, ZeroDivisionError):
print("苹果不分了")
print("程序正常退出")
# 此示例示意 try-except语句的用法
def div_apple(n):
print("%d个苹果您想分给几个人?" % n)
s = input("请输入人数: ")
cnt = int(s)
# &--此处可能触发ValueError类型的错误
result = n / cnt
# &-- 此处可能会触发ZeroDivisionError类型的错误
print("每个人分了%d个苹果" % result)
div_apple(10)
# 此函数可能会触发错误,分苹果失败
print("分完苹果")
except ValueError:
print("苹果不分了")
print("其它类型的错误已捕获!")
print("程序正常退出")
写一个函数:
def get_score():
此函数来获取用户输入的学生成绩信息(1~100的整数)
如果用户输入出现异常则此函数返回0,否则返回用户输入的成绩
def get_score():
score = int(input("请输入成绩:"))
if 0 &=score &=100 :
return score
return score
score = get_score()
print("您输入的成绩是:",score)
#此示例示意 try-except语句中 as 的用法
def div_apple(n):
print("%d个苹果您想分给几个人?" % n)
s = input("请输入人数: ")
cnt = int(s)
&--此处可能触发ValueError类型的错误
result = n / cnt
&-- 此处可能会触发ZeroDivisionError类型的错误
print("每个人分了%d个苹果" % result)
div_apple(10)
# 此函数可能会触发错误,分苹果失败
print("分完苹果")
except ValueError as e:
print("苹果不分了")
print("错误的值是:", e)
print("其它类型的错误已捕获!")
print("程序正常退出")
try-finally语句
可能触发异常的语句
一定要执行的最终语句
1.finally 子句不可以省略
2.一定不存在except子句
通常用try-finally语句来做触发异常时必须要处理的事情,无论异常是否发生,finally子句都会被执行
try-finally 语句不会改变程序的状态(正常/异常)状态
def fry_egg():
print('打开气')
count = int(input("鸡蛋数:"))
print("共煎了",count,'个鸡蛋')
print("关闭气")
raise 语句
触发一个错误,让程序进入异常状态
raise 异常类型
raise 异常对象
# 此示例示意用raise语句来触发异常
def make_exception():
print("begin")
# 触发ValueError类型的异常并进入异常状态
# raise ValueError
err = ValueError("这是我自己定义的一个错误")
print("end")
make_exception()
make_exception()
print("make_exception调用结束")
# except ValueError as e:
print("try里出现了值错误通知,已捕获!!!")
print("接收的异常通知是: ", e)
写一个函数get_age() 用来获取一个人的年龄信息
此函数规则用户只能输入1~140之间的整数。如果用户输入其他的数则直接触发
ValueError类型的错误!
def get_age():
def get_age():
s = input("请输入年龄(1~140): ")
a = int(s)
# int函数里可能会触发ValueError类型的错误
if 1 &= a &= 140:
raise ValueError("用户输入的整数不在1~140之间")
age = get_age()
print("用户输入的年龄是:", age)
except ValueError as err:
print("用户输入的不是1~140的整数!!,获取年龄失败")
assert 语句(断言语句)
assert 真值表达式,错误数据(通常是字符串)
当真值表达式为False时,用错误数据创建一个AssertionError类型的错误,并进入异常状态
if 真值表达式== False:
raise AssertionError(错误数据)
try-except
捕获异常,尝试接收异常通知
try-finally
执行一定要执行的语句
发送异常通知,将程序转为异常状态(进入异常流程)
根据条件来触发AssertionError类型的异常
with 语句(以后再学)
为什么要用异常处理机制
在程序调用层数较深时,向主调程序传递错误信息需要层层return返回比较麻烦,
所以用异常处理机制来解决此类问题
print("开始建房子打地基")
err = ValueError("打地基挖出古董")
print("完成打地基工作")
return "地基完成"
print("开始建设地上部分")
# err = ValueError("规划要建高压线")
# return err
print("地上部分建完..")
return "地上完成"
# 建地上部分
return r1 + r2
def built_house():
'''接项目的人'''
return f3()
h = built_house()
# 建房子的函数,此函数应当返回一个房子对象
except ValueError as e:
print("错误原因是:", e)
print('改建博物管')
1.一个球从100米高空落下,每次落地后反弹高度为原高度的一半,在落下,写程序
1)算出皮球在第10次落地后反弹多高
2)打印除皮球共经历了多少米路程
2.分解质因数,输入一个正整数,分解质因数
如输入:90,则打印:
90= 2* 3 * 3 * 5
(质因数是指最小能被原数整除的素数(不包含1))
3.写程序打印杨辉三角(只打印6层)
1 5 10 10 5 1
# 1) 算出皮球在第10次落地后反弹多高
# 用循来来实现
def get_last_height(height, times):
for _ in range(times):
height /= 2
return height
# 用递归来实现
# def get_last_height(height, times):
if times == 0:
return 100
return get_last_height(height, times - 1) / 2
print(get_last_height(100, 10))
# 2) 打印出皮球共经历了多少米路程
def get_distance(height, times):
for _ in range(times):
s += height + height / 2
height /= 2
print(get_distance(100, 10))
def is_prime(x):
return False
for i in range(2, x):
if x % i == 0:
return False
return True
return True
def get_yinshu_list(n):
'''用循环实现'''
L = [] # 用来存放所有的质因数
# x代表未分解的数
while not is_prime(x):
# 当x不是素数时开始循环
for i in range(2, x):
if x % i == 0 and is_prime(i):
# 被整除,i是质因数
L.append(i)
x = int(x / i)
L.append(x)
n = int(input("请输入一个正整数: "))
# print(get_yinshu_list(n))
yinshu = get_yinshu_list(n)
s = '*'.join([str(x) for x in yinshu])
print("%d = %s" % (n, s))
def get_yanghui_list(n): # n代表层数
'''此函数用于返回每一层的列表的列表'''
layers = []
# 用于存储每一行的数据[[1], [1, 1], [1, 2, 1], ...]
for _ in range(n):
# 循环,每次加入layers中一行
layers.append(L)
# 先把第一行加入
# 算出下一行。再用L重新绑定
one_line = [1]
# 最左边的1
# 算出中间的数字
for i in range(len(L) - 1):
one_line.append(L[i] + L[i + 1])
one_line.append(1)
# 加入最右边的1
L = one_line
# 让L 绑定新算出的一行
return layers
if __name__ == '__main__':
# print(get_yanghui_list(6))
for l in get_yanghui_list(6):
说明写代码时,我们有时希望捕捉到程序异常但程序不退出,有时候不确定程序是否会异常,有时候希望自己定义异常,中断程序运行。异常处理raise使用raise抛出异常,一旦执行了raise语句,raise后...
异常处理:
try ...except
try代码块放置容易发生异常的语句:except代码块放置处理异常的语句
try ...except...finally finally代码快是任何时候都会执...
# -----------------------
# __Author : tyran
# __Date : 17-11-13
# -----------------------
# 异常处理
自行总结的raise语句用法
1、try-except[as reason] 一旦在某处出错了,之后的程序代码不会被执行了
可以添加else
# sum = 1 + '1'
1、try块和异常处理
博客参考#include
double func(int x,int y)
if(y == 0)
try语句是这样工作的:
  首先,运行try子句(在try和except之间的语句)。
  如果没有发生例外,跳过except子句,try语句运行完毕。
  如果在try子句中发生了例外错...
http://www.iplaypython.com/jinjie/assert.html
使用assert断言是学习python一个非常好的习惯,assert断言句语格式及用法...
要故意出发异常,可以使用raise语句,形式如下:
#manually trigger an exception
raise, #pass extra data to catche...
异常发生在程序执行的过程中,如果python无法正常处理程序就会发生异常,导致整个程序终止执行,python中使用try/except语句可以捕获异常。
try/except
异常的种类有很多,在...
没有更多推荐了,第三章 其他的知识点
3.1. 垃圾回收(一)
3.2. 垃圾回收(二)
3.3. 垃圾回收(三)-gc模块
3.4. 内建属性
3.5. 内建函数
3.6. 集合set
3.7. functools
3.10. 编码风格
3.1. 垃圾回收(一)
1. 小整数对象池
整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池, 避免为整数频繁申请和销毁内存空间。
Python 对小整数的定义是 [-5, 257) 这些整数对象是提前建立好的,不会被垃圾回收。在一个 Python 的程序中,所有位于这个范围内的整数使用的都是同一个对象.
同理,单个字母也是这样的。
但是当定义2个相同的字符串时,引用计数为0,触发垃圾回收
2. 大整数对象池
每一个大整数,均创建一个新的对象。
3. intern机制
a1 = "HelloWorld"
a2 = "HelloWorld"
a3 = "HelloWorld"
a4 = "HelloWorld"
a5 = "HelloWorld"
a6 = "HelloWorld"
a7 = "HelloWorld"
a8 = "HelloWorld"
a9 = "HelloWorld"
python会不会创建9个对象呢?在内存中会不会开辟9个”HelloWorld”的内存空间呢? 想一下,如果是这样的话,我们写10000个对象,比如a1=”HelloWorld”…..a1000=”HelloWorld”, 那他岂不是开辟了1000个”HelloWorld”所占的内存空间了呢?如果真这样,内存不就爆了吗?所以python中有这样一个机制——intern机制,让他只占用一个”HelloWorld”所占的内存空间。靠引用计数去维护何时释放。
小整数[-5,257)共用对象,常驻内存
单个字符共用对象,常驻内存
单个单词,不可修改,默认开启intern机制,共用对象,引用计数为0,则销毁 单词垃圾回收
字符串(含有空格),不可修改,没开启intern机制,不共用对象,引用计数为0,销毁
大整数不共用内存,引用计数为0,销毁 大整数垃圾回收
数值类型和字符串类型在 Python 中都是不可变的,这意味着你无法修改这个对象的值,每次对变量的修改,实际上是创建一个新的对象 不可变
3.2. 垃圾回收(二)
1. Garbage collection(GC垃圾回收)
现在的高级语言如java,c#等,都采用了垃圾收集机制,而不再是c,c++&里用户自己管理维护内存的方式。自己管理内存极其自由,可以任意申请&内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患。 &对于一个字符串、列表、类甚至数值都是对象,且定位简单易用的语言,自然不会让用户去处理如何分配回收内存的问题。 &python里也同java一样采用了垃圾收集机制,不过不一样的是: python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略
引用计数机制:
python里每一个东西都是对象,它们的核心就是一个结构体:PyObject
typedef str&uct_obj&ect {&
struct_&typeobject *ob_&
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除&,它的ob_refcnt就会减少
if (--(op)-&ob_refcnt != 0) \
__Py_Dealloc((PyObject *)(op))
当引用计数为0时,该对象生命就结束了。
引用计数机制的优点:
实时性:一旦没有引用,内存就直接释放了。不用像其他机制等到特定时机。实时性还带来一个好处:处理回收内存的时间分摊到了平时。
引用计数机制的缺点:
维护引用计数消耗资源
list1 = []
list2 = []
list1.append(list2)
list2.append(list1)
list1与list2相互引用,如果不存在其他对象对它们的引用,list1与list2的引用计数也仍然为1,所占用的内存永远无法被回收,这将是致命的。& 对于如今的强大硬件,缺点1尚可接受,但是循环引用导致内存泄露,注定python还将引入新的回收机制。(标记清除和分代收集)
2. 画说 Ruby 与 Python 垃圾回收
2.1 应用程序那颗跃动的心
GC系统所承担的工作远比”垃圾回收”多得多。实际上,它们负责三个重要任务。它们
为新生成的对象分配内存&
识别那些垃圾对象,并且&
从垃圾对象那回收内存。&
如果将应用程序比作人的身体:所有你所写的那些优雅的代码,业务逻辑,算法,应该就是大脑。以此类推,垃圾回收机制应该是那个身体器官呢&?(我从RuPy听众那听到了不少有趣的答案:腰子、白血球 :) )
我认为垃圾回收就是应用程序那颗跃动的心。像心脏为身体其他器官提供血液和营养物那样,垃圾回收器为你的应该程序提供内存和对象。如果心&脏停跳,过不了几秒钟人就完了。如果垃圾回收器停止工作或运行迟缓,像动脉阻塞,你的应用程序效率也会下降,直至最终死掉。
2.2 一个简单的例子
运用实例一贯有助于理论的理解。下面是一个简单类,分别用Python和Ruby写成,我们今天就以此为例:
顺便提一句,两种语言的代码竟能如此相像:Ruby 和 Python &在表达同一事物上真的只是略有不同。但是在这两种语言的内部实现上是否也如此相似呢?
2.3 Ruby 的对象分配
当我们执行上面的Node.new(1)时,Ruby到底做了什么?Ruby是如何为我们创建新的对象的呢? 出乎意料的是它做的非常少。实际上,早在代码开&始执行前,Ruby就提前创建了成百上千个对象,并把它们串在链表上,名曰:可用列表。下图所示为可用列表的概念图:
想象一下每个白色方格上都标着一个”未使用预创建对象”。当我们调用 Node.new ,Ruby只需取一个预创建对象给我们使用即可:
上图中左侧灰格表示我们代码中使用的当前对象,同时其他白格是未使用对象。(请注意:无疑我的示意图是对实际的简化。实际上,Ruby会用另一&个对象来装载字符串”ABC”,另一个对象装载Node类定义,还有一个对象装载了代码中分析出的抽象语法树,等等)
如果我们再次调用 Node.new,Ruby将递给我们另一个对象:
这个简单的用链表来预分配对象的算法已经发明了超过50年,而发明人这是赫赫有名的计算机科学家John McCarthy,一开始是用Lisp实现的。Lisp&不仅是最早的函数式编程语言,在计算机科学领域也有许多创举。其一就是利用垃圾回收机制自动化进行程序内存管理的概念。
标准版的Ruby,也就是众所周知的”Matz’s Ruby Interpreter”(MRI),所使用的GC算法与McCarthy在1960年的实现方式很类似。无论好坏,Ruby的垃&圾回收机制已经53岁高龄了。像Lisp一样,Ruby预先创建一些对象,然后在你分配新对象或者变量的时候供你使用。
2.4 Python 的对象分配
我们已经了解了Ruby预先创建对象并将它们存放在可用列表中。那Python又怎么样呢?
尽管由于许多原因Python也使用可用列表(用来回收一些特定对象比如 list),但在为新对象和变量分配内存的方面Python和Ruby是不同的。
例如我们用Pyhon来创建一个Node对象:
与Ruby不同,当创建对象时Python立即向操作系统请求内存。(&Python实际上实现了一套自己的内存分配系统,在操作系统堆之上提供了一个抽象层。但是我今天不展开说了。)
当我们创建第二个对象的时候,再次像OS请求内存:
看起来够简单吧,在我们创建对象的时候,Python会花些时间为我们找到并分配内存。
2.5 Ruby 开发者住在凌乱的房间里
Ruby把无用的对象留在内存里,直到下一次GC执行
回过来看Ruby。随着我们创建越来越多的对象,Ruby会持续寻可用列表里取预创建对象给我们。因此,可用列表会逐渐变短:
…然后更短:
请注意我一直在为变量n1赋新值,Ruby把旧值留在原处。”ABC”,”JKL”和”MNO”三个Node实例还滞留在内存中。Ruby不会立即清除代码中不再使用的&旧对象!Ruby开发者们就像是住在一间凌乱的房间,地板上摞着衣服,要么洗碗池里都是脏盘子。作为一个Ruby程序员,无用的垃圾对象会一直环&绕着你。
2.6 Python 开发者住在卫生之家庭
用完的垃圾对象会立即被Python打扫干净
Python与Ruby的垃圾回收机制颇为不同。让我们回到前面提到的三个Python Node对象:
在内部,创建一个对象时,Python总是在对象的C结构体里保存一个整数,称为 引用数。期初,Python将这个值设置为1:
值为1说明分别有个一个指针指向或是引用这三个对象。假如我们现在创建一个新的Node实例,JKL:
与之前一样,Python设置JKL的引用数为1。然而,请注意由于我们改变了n1指向了JKL,不再指向ABC,Python就把ABC的引用数置为0了。 &此刻,Python垃圾回收器立刻挺身而出!每当对象的引用数减为0,Python立即将其释放,把内存还给操作系统:
上面Python回收了ABC Node实例使用的内存。记住,Ruby弃旧对象原地于不顾,也不释放它们的内存。
Python的这种垃圾回收算法被称为引用计数。是George-Collins在1960年发明的,恰巧与John &McCarthy发明的可用列表算法在同一年出现。就像Mike-Bernstein在6月份哥谭市Ruby大会杰出的垃圾回收机制演讲中说的: &”1960年是垃圾收集器的黄金年代…”
Python开发者工作在卫生之家,你可以想象,有个患有轻度OCD(一种强迫症)&的室友一刻不停地跟在你身后打扫,你一放下脏碟子或杯子,有个家伙已经准备好把它放进洗碗机了!
现在来看第二例子。加入我们让n2引用n1:
上图中左边的DEF的引用数已经被Python减少了,垃圾回收器会立即回收DEF实例。同时JKL的引用数已经变为了2 ,因为n1和n2都指向它。
2.7 标记-清除
最终那间凌乱的房间充斥着垃圾,再不能岁月静好了。在Ruby程序运行了一阵子以后,可用列表最终被用光光了:
此刻所有Ruby预创建对象都被程序用过了(它们都变灰了),可用列表里空空如也(没有白格子了)。
此刻Ruby祭出另一McCarthy发明的算法,名曰:标记-清除。首先Ruby把程序停下来,Ruby用”地球停转垃圾回收大法”。之后Ruby轮询所有指针,变&量和代码产生别的引用对象和其他值。同时Ruby通过自身的虚拟机便利内部指针。标记出这些指针引用的每个对象。我在图中使用M表示。
上图中那三个被标M的对象是程序还在使用的。在内部,Ruby实际上使用一串位值,被称为:可用位图(&译注:还记得《编程珠玑》里的为突发排序吗,这对离散度不高的有限整数集合具有很强的压缩效果,用以节约机器的资源。)&,来跟踪对象是否被标记了。
如果说被标记的对象是存活的,剩下的未被标记的对象只能是垃圾,这意味着我们的代码不再会使用它了。我会在下图中用白格子表示垃圾对象:
接下来Ruby清除这些无用的垃圾对象,把它们送回到可用列表中:
在内部这一切发生得迅雷不及掩耳,因为Ruby实际上不会吧对象从这拷贝到那。而是通过调整内部指针,将其指向一个新链表的方式,来将垃圾对&象归位到可用列表中的。
现在等到下回再创建对象的时候Ruby又可以把这些垃圾对象分给我们使用了。在Ruby里,对象们六道轮回,转世投胎,享受多次人生。
2.8 标记-删除 vs. 引用计数
乍一看,Python的GC算法貌似远胜于Ruby的:宁舍洁宇而居秽室乎?为什么Ruby宁愿定期强制程序停止运行,也不使用Python的算法呢?
然而,引用计数并不像第一眼看上去那样简单。有许多原因使得不许多语言不像Python这样使用引用计数GC算法:
首先,它不好实现。Python不得不在每个对象内部留一些空间来处理引用数。这样付出了一小点儿空间上的代价。但更糟糕的是,每个简单的操作&(像修改变量或引用)都会变成一个更复杂的操作,因为Python需要增加一个计数,减少另一个,还可能释放对象。
第二点,它相对较慢。虽然Python随着程序执行GC很稳健(一把脏碟子放在洗碗盆里就开始洗啦),但这并不一定更快。Python不停地更新着众多&引用数值。特别是当你不再使用一个大数据结构的时候,比如一个包含很多元素的列表,Python可能必须一次性释放大量对象。减少引用数就成了&一项复杂的递归过程了。
最后,它不是总奏效的。引用计数不能处理环形数据结构–也就是含有循环引用的数据结构。
3. Python中的循环数据结构以及引用计数
3.1 循环引用
通过上篇,我们知道在Python中,每个对象都保存了一个称为引用计数的整数值,来追踪到底有多少引用指向了这个对象。无论何时,如果我们程&序中的一个变量或其他对象引用了目标对象,Python将会增加这个计数值,而当程序停止使用这个对象,则Python会减少这个计数值。一旦计数值&被减到零,Python将会释放这个对象以及回收相关内存空间。
从六十年代开始,计算机科学界就面临了一个严重的理论问题,那就是针对引用计数这种算法来说,如果一个数据结构引用了它自身,即如果这个&数据结构是一个循环数据结构,那么某些引用计数值是肯定无法变成零的。为了更好地理解这个问题,让我们举个例子。下面的代码展示了一些上&周我们所用到的节点类:
我们有一个”构造器”(在Python中叫做 init ),在一个实例变量中存储一个单独的属性。在类定义之后我们创建两个节点,ABC以及DEF,在图&中为左边的矩形框。两个节点的引用计数都被初始化为1,因为各有两个引用指向各个节点(n1和n2)。
现在,让我们在节点中定义两个附加的属性,next以及prev:
跟Ruby不同的是,Python中你可以在代码运行的时候动态定义实例变量或对象属性。这看起来似乎有&点像Ruby缺失了某些有趣的魔法。(&声明下我不是一个Python程序员,所以可能会存在一些命名方面的错误)。我们设置 n1.next 指向 n&2,同时设置 n2.prev 指回 &n1。现在,我们的两个节点使用循环引用的方式构成了一个双向链表。同时请注意到 ABC 以及 DEF &的引用计数值已经增加到了2。这里有两个指针指向了每个节点:首先是 n1 以及 n2,其次就是 next 以及 prev。
现在,假定我们的程序不再使用这两个节点了,我们将 n1 和 n2 都设置为null(Python中是None)。
好了,Python会像往常一样将每个节点的引用计数减少到1。
3.2 在Python中的零代(Generation Zero)
请注意在以上刚刚说到的例子中,我们以一个不是很常见的情况结尾:我们有一个“孤岛”或是一组未使用的、互相指向的对象,但是谁都没有外部&引用。换句话说,我们的程序不再使用这些节点对象了,所以我们希望Python的垃圾回收机制能够足够智能去释放这些对象并回收它们占用的内存&空间。但是这不可能,因为所有的引用计数都是1而不是0。Python的引用计数算法不能够处理互相指向自己的对象。
这就是为什么Python要引入Generational GC算法的原因!正如Ruby使用一个链表(free list)来持续追踪未使用的、自由的&对象一样,Python使用&一种不同的链表来持续追踪活跃的对象。而不将其称之为“活跃列表”,Python的内部C代码将其称为零代(Generation Zero)&。每次当你创建一个对象或其他什么值的时候,Python会将其加入零代链表:
从上边可以看到当我们创建ABC节点的时候,Python将其加入零代链表。请注意到这并不是一个真正的列表,并不能直接在你的代码中访问,事实上&这个链表是一个完全内部的Python运行时。 相似的,当我们创建DEF节点的时候,Python将其加入同样的链表:
现在零代包含了两个节点对象。(他还将包含Python创建的每个其他值,与一些Python自己使用的内部值。)
3.3 检测循环引用
随后,Python会循环遍历零代列表上的每个对象,检查列表中每个互相引用的对象,根据规则减掉其引用计数。在这个过程中,Python会一个接一&个的统计内部引用的数量以防过早地释放对象。
为了便于理解,来看一个例子:
从上面可以看到 ABC 和 DEF &节点包含的引用数为1.有三个其他的对象同时存在于零代链表中,蓝色的箭头指示了有一些对象正在被零代链表之外的其他对象所引用。(&接下来我们会看到,Python中同时存在另外两个分别被称为一代和二代的链表)。这些对象有着更高的引用计数因为它们正在被其他指针所指向着。
接下来你会看到Python的GC是如何处理零代链表的。
通过识别内部引用,Python能够减少许多零代链表对象的引用计数。在上图的第一行中你能够看见ABC和DEF的引用计数已经变为零了,这意味着收&集器可以释放它们并回收内存空间了。剩下的活跃的对象则被移动到一个新的链表:一代链表。
从某种意义上说,Python的GC算法类似于Ruby所用的标记回收算法。周期性地从一个对象到另一个对象追踪引用以确定对象是否还是活跃的,正在&被程序所使用的,这正类似于Ruby的标记过程。
Python中的GC阈值
Python什么时候会进行这个标记过程?随着你的程序运行,Python解释器保持对新创建的对象,以及因为引用计数为零而被释放掉的对象的追踪。&从理论上说,这两个值应该保持一致,因为程序新建的每个对象都应该最终被释放掉。
当然,事实并非如此。因为循环引用的原因,并且因为你的程序使用了一些比其他对象存在时间更长的对象,从而被分配对象的计数值与被释放对&象的计数值之间的差异在逐渐增长。一旦这个差异累计超过某个阈值,则Python的收集机制就启动了,并且触发上边所说到的零代算法,释放“浮动&的垃圾”,并且将剩下的对象移动到一代列表。
随着时间的推移,程序所使用的对象逐渐从零代列表移动到一代列表。而Python对于一代列表中对象的处理遵循同样的方法,一旦被分配计数值与&被释放计数值累计到达一定阈值,Python会将剩下的活跃对象移动到二代列表。
通过这种方法,你的代码所长期使用的对象,那些你的代码持续访问的活跃对象,会从零代链表转移到一代再转移到二代。通过不同的阈值设置,P&ython可以在不同的时间间隔处理这些对象。Python处理零代最为频繁,其次是一代然后才是二代。
来看看代垃圾回收算法的核心行为:垃圾回收器会更频繁的处理新对象。一个新的对象即是你的程序刚刚创建的,而一个来的对象则是经过了几个&时间周期之后仍然存在的对象。Python会在当一个对象从零代移动到一代,或是从一代移动到二代的过程中提升(promote)这个对象。
为什么要这么做?这种算法的根源来自于弱代假说(weak generational hypothesis)&。这个假说由两个观点构成:首先是年亲的对象通常死得也快,而老对象则很有可能存活更长的时间。
假定现在我用Python或是Ruby创建一个新对象:
根据假说,我的代码很可能仅仅会使用ABC很短的时间。这个对象也许仅仅只是一个方法中的中间结果,并且随着方法的返回这个对象就将变成垃圾&了。大部分的新对象都是如此般地很快变成垃圾。然而,偶尔程序会创建一些很重要的,存活时间比较长的对象-例如web应用中的session变量或是&配置项。
通过频繁的处理零代链表中的新对象,Python的垃圾收集器将把时间花在更有意义的地方:它处理那些很快就可能变成垃圾的新对象。同时只在很&少的时候,当满足阈值的条件,收集器才回去处理那些老变量。
3.3. 垃圾回收(三)-gc模块
一.垃圾回收机制
Python中的垃圾回收是以引用计数为主,分代收集为辅。
1、导致引用计数+1的情况
对象被创建,例如a=23
对象被引用,例如b=a
对象被作为参数,传入到一个函数中,例如func(a)
对象作为一个元素,存储在容器中,例如list1=[a,a]
2、导致引用计数-1的情况
对象的别名被显式销毁,例如del a
对象的别名被赋予新的对象,例如a=24
一个对象离开它的作用域,例如f函数执行完毕时,func函数中的局部变量(全局变量不会)
对象所在的容器被销毁,或从容器中删除对象
3、查看一个对象的引用计数
import sys
a = “hello world”
sys.getrefcount(a)
可以查看a对象的引用计数,但是比正常计数大1,因为调用函数的时候传入a,这会让a的引用计数+1
二.循环引用导致内存泄露
引用计数的缺陷是循环引用的问题
class ClassA():
def __init__(self):
print('object born,id:%s'%str(hex(id(self))))
while True:
c1 = ClassA()
c2 = ClassA()
gc.disable()
执行f2(),进程占用的内存会不断增大。
创建了c1,c2后这两块内存的引用计数都是1,执行c1.t=c2和c2.t=c1后,这两块内存的引用计数变成2.&
在del c1后,内存1的对象的引用计数变为1,由于不是为0,所以内存1的对象不会被销毁,所以内存2的对象的引用数依然是2,在del &c2后,同理,内存1的对象,内存2的对象的引用数都是1。
虽然它们两个的对象都是可以被销毁的,但是由于循环引用,导致垃圾回收器都不会回收它们,所以就会导致内存泄露。
三.垃圾回收
class ClassA():
def __init__(self):
print('object born,id:%s'%str(hex(id(self))))
print("-----0------")
c1 = ClassA()
c2 = ClassA()
print("-----1------")
print("-----2------")
print(gc.garbage)
print("-----3------")
print(gc.collect())
print("-----4------")
print(gc.garbage)
print("-----5------")
if __name__ == '__main__':
gc.set_debug(gc.DEBUG_LEAK)
python2运行结果:
-&-&---0------&
o&b&ject born,&id:0x724b20&
o&b&ject born,&id:0x724b48&
-&-&---1------&
-&-&---2------&
-&----3------&
g&c: collectable &ClassA instanc&e at 0x724b20&&
g&c: collectable &ClassA instanc&e at 0x724b48&&
g&c: collectable &dict 0x723300&&
g&c: collectable &dict 0x71bf60&&
-----4------&
[&__main__.ClassA instance at 0x724b20&, &__main__.ClassA instance at 0x724b48&, {'t': &__main__.ClassA instance at 0x724b48&}, &{'t': &__main__.ClassA instance at 0x724b20&}]
-----5------
垃圾回收后的对象会放在gc.garbage列表里面
gc.collect()会返回不可达的对象数目,4等于两个对象以及它们对应的dict
有三种情况会触发垃圾回收:
调用gc.collect(),
当gc模块的计数器达到阀值的时候。
程序退出的时候
四.gc模块常用功能解析
gc模块提供一个接口给开发者设置垃圾回收的选项。上面说到,采用引用计数的方法管理内存的一个缺陷是循环引用,而gc模块的一个主要功能就&是解决循环引用的问题。
常用函数:
1、gc.set_debug(flags) 设置gc的debug日志,一般设置为gc.DEBUG_LEAK
2、gc.collect([generation]) 显式进行垃圾回收,可以输入参数,0代表只检查第一代的对象,1代表检查一,二代的对象,2代表检查一,二,三&代的对象,如果不传参数,执行一个full collection,也就是等于传2。 返回不可达(unreachable objects)对象的数目
3、gc.get_threshold() 获取的gc模块中自动执行垃圾回收的频率。
4、gc.set_threshold(threshold0[, threshold1[, threshold2]) 设置自动执行垃圾回收的频率。
5、gc.get_count() 获取当前自动执行垃圾回收的计数器,返回一个长度为3的列表
gc模块的自动垃圾回收机制
必须要import gc模块,并且is_enable()=True才会启动自动垃圾回收。
这个机制的主要作用就是发现并处理不可达的垃圾对象。
垃圾回收=垃圾检查+垃圾回收
在Python中,采用分代收集的方法。把对象分为三代,一开始,对象在创建的时候,放在一代中,如果在一次一代的垃圾检查中,改对象存活下来&,就会被放到二代中,同理在一次二代的垃圾检查中,该对象存活下来,就会被放到三代中。
gc模块里面会有一个长度为3的列表的计数器,可以通过gc.get_count()获取。
例如(488,3,0)&,其中488是指距离上一次一代垃圾检查,Python分配内存的数目减去释放内存的数目,注意是内存分配,而不是引用计数的增加。例如:
print gc.get_count()
a = ClassA()
print gc.get_count()
print gc.get_count()
3是指距离上一次二代垃圾检查,一代垃圾检查的次数,同理,0是指距离上一次三代垃圾检查,二代垃圾检查的次数。
gc模快有一个自动垃圾回收的阀值,即通过gc.get_threshold函数获取到的长度为3的元组,例如(700,10,10) &每一次计数器的增加,gc模块就会检查增加后的计数是否达到阀值的数目,如果是,就会执行对应的代数的垃圾检查,然后重置计数器
例如,假设阀值是(700,10,10):
当计数器从(699,3,0)增加到(700,3,0),gc模块就会执行gc.collect(0),即检查一代对象的垃圾,并重置计数器为(0,4,0)
当计数器从(699,9,0)增加到(700,9,0),gc模块就会执行gc.collect(1),即检查一、二代对象的垃圾,并重置计数器为(0,0,1)
当计数器从(699,9,9)增加到(700,9,9),gc模块就会执行gc.collect(2),即检查一、二、三代对象的垃圾,并重置计数器为(0,0,0)
gc模块唯一处理不了的是循环引用的类都有del方法,所以项目中要避免定义del方法
class ClassA():
gc.set_debug(gc.DEBUG_LEAK)
a = ClassA()
b = ClassA()
a.next = b
b.prev = a
print "--1--"
print gc.collect()
print "--2--"
print "--3--"
print "--3-1--"
print gc.collect()
print "--4--"
运行结果:
gc: collectable &ClassA instance at 0x21248c8&
gc: collectable &ClassA instance at 0x21248f0&
gc: collectable &dict 0x2123030&
gc: collectable &dict 0x2123150&
如果把del打开,运行结果为:
gc: uncollectable &ClassA instance at 0x6269b8&
gc: uncollectable &ClassA instance at 0x6269e0&
gc: uncollectable &dict 0x61bed0&
gc: uncollectable &dict 0x6230c0&
3.4. 内建属性
"teachclass.py"
class Person(object):
python3.5中类的内建属性和方法 py3class
经典类(旧式类),早期如果没有要继承的父类,继承里空着不写的类
class Person:
子类没有实现__init__方法时,默认自动调用父类的。 如定义__init__方法时,需自己手动调用父类的 __init__方法
常用专有属性
构造初始化函数
创建实例后,赋值时使用,在__new__后
生成实例所需属性
创建实例时
实例所在的类
实例.__class__
实例字符串表示,可读性
print(类实例),如没实现,使用repr结果
实例字符串表示,准确性
类实例 回车 或者 print(repr(类实例))
del删除实例
实例自定义属性
vars(实例.__dict__)
类文档,子类不继承
help(类或实例)
__getattribute__
属性访问拦截器
访问实例属性时
类的所有父类构成元素
类名.__bases__
__getattribute__例子:
class Itcast(object):
def __init__(self,subject1):
self.subject1 = subject1
self.subject2 = 'cpp'
def __getattribute__(self,obj):
if obj == 'subject1':
print('log subject1')
return 'redirect python'
return object.__getattribute__(self,obj)
def show(self):
print('this is Itcast')
s = Itcast("python")
print(s.subject1)
print(s.subject2)
log subject1
redirect python
__getattribute__的坑
class Person(object):
def __getattribute__(self,obj):
print("---test---")
if obj.startswith("a"):
return "hahha"
return self.test
def test(self):
print("heihei")
t.Person()
3.5. 内建函数
Build-in Function,启动python解释器,输入dir(builtins), &可以看到很多python解释器启动后默认加载的属性和函数,这些函数称之为内建函数, &这些函数因为在编程时使用较多,cpython解释器用c语言实现了这些函数,启动解释器 时默认加载。
这些函数数量众多,不宜记忆,开发时不是都用到的,待用到时再help(function), &查看如何使用,或结合百度查询即可,在这里介绍些常用的内建函数。
range(stop) -& list of integers
range(start, stop[, step]) -& list of integers
start:计数从start开始。默认是从0开始。例如range(5)等价于range(0, 5);
stop:到stop结束,但不包括stop.例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5
step:每次跳跃的间距,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)
python2中range返回列表,python3中range返回一个迭代值。如果想得到列表,可通过list函数
a = range(5)
创建列表的另外一种方法
In [21]: testList = [x+2 for x in range(5)]
In [22]: testList
Out[22]: [2, 3, 4, 5, 6]
map函数会根据提供的函数对指定序列做映射
map(function, sequence[, sequence, ...]) -& list
function:是一个函数
sequence:是一个或多个序列,取决于function需要几个参数
返回值是一个list
参数序列中的每一个元素分别调用function函数,返回包含每次function函数返回值的list。
map(lambda x: x*x, [1, 2, 3])
map(lambda x, y: x+y, [1, 2, 3], [4, 5, 6])
def f1( x, y ):
return (x,y)
l1 = [ 0, 1, 2, 3, 4, 5, 6 ]
l2 = [ 'Sun', 'M', 'T', 'W', 'T', 'F', 'S' ]
l3 = map( f1, l1, l2 )
print(list(l3))
filter函数会对指定序列执行过滤操作
filter(...)
filter(function or None, sequence) -& list, tuple, or string
Return those items of sequence for which function(item) is true.
function is None, return the items that are true.
If sequence is a tuple
or string, return the same type, else return a list.
function:接受一个参数,返回布尔值True或False
sequence:序列可以是str,tuple,list
filter函数会对序列参数sequence中的每个元素调用function函数,最后返回的结果包含调用结果为True的元素。
返回值的类型和参数sequence的类型相同
filter(lambda x: x%2, [1, 2, 3, 4])
filter(None, "she")
reduce函数,reduce函数会对参数序列中元素进行累积
reduce(...)
reduce(function, sequence[, initial]) -& value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5).
If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
function:该函数有两个参数
sequence:序列可以是str,tuple,list
initial:固定初始值
reduce依次从sequence中取一个元素,和上一次调用function的结果做参数再次调用function。 第一次调用function时,如果提供initial参数,会以sequence中的第一个元素和initial 作为参数调用function,否则会以序列sequence中的前两个元素做参数调用function。 注意function函数不能为None。
reduce(lambda x, y: x+y, [1,2,3,4])
reduce(lambda x, y: x+y, [1,2,3,4], 5)
reduce(lambda x, y: x+y, ['aa', 'bb', 'cc'], 'dd')
'ddaabbcc'
在Python3里,reduce函数已经被从全局名字空间里移除了, 它现在被放置在fucntools模块里用的话要先引入: from functools import reduce
sorted(...)
sorted(iterable, cmp=None, key=None, reverse=False) --& new sorted list
3.6. 集合set
集合与之前列表、元组类似,可以存储多个数据,但是这些数据是不重复的
集合对象还支持union(联合), intersection(交), difference(差)和sysmmetric_difference(对称差集)等数学运算.
&&& x = set('abcd')
{'c', 'a', 'b', 'd'}
&&& type(x)
&class 'set'&
&&& y = set(['h','e','l','l','o'])
{'h', 'e', 'o', 'l'}
&&& z = set('spam')
{'s', 'a', 'm', 'p'}
&&& y&z #交集
&&& x&z #交集
&&& x|y #并集
{'a', 'e', 'd', 'l', 'c', 'h', 'o', 'b'}
&&& x-y #差集
{'c', 'a', 'b', 'd'}
&&& x^z #对称差集(在x或z中,但不会同时出现在二者中)
{'m', 'd', 's', 'c', 'b', 'p'}
&&& len(x)
&&& len(y)
&&& len(z)
3.7. functools
functools 是python2.5被引人的,一些工具函数放在此包里。
python2.7中
python3.5中
import functools
dir(functools)
运行结果:
['MappingProxyType',
'WRAPPER_ASSIGNMENTS',
'WRAPPER_UPDATES',
'WeakKeyDictionary',
'_CacheInfo',
'_HashedSeq',
'__all__',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'_c3_merge',
'_c3_mro',
'_compose_mro',
'_convert',
'_find_impl',
'_ge_from_gt',
'_ge_from_le',
'_ge_from_lt',
'_gt_from_ge',
'_gt_from_le',
'_gt_from_lt',
'_le_from_ge',
'_le_from_gt',
'_le_from_lt',
'_lru_cache_wrapper',
'_lt_from_ge',
'_lt_from_gt',
'_lt_from_le',
'_make_key',
'cmp_to_key',
'get_cache_token',
'lru_cache',
'namedtuple',
'partial',
'partialmethod',
'singledispatch',
'total_ordering',
'update_wrapper',
python3中增加了更多工具函数,做业务开发时大多情况下用不到,此处介绍使用频率较高的2个函数。
partial函数(偏函数)
把一个函数的某些参数设置默认值,返回一个新的函数,调用这个新函数会更简单。
import functools
def showarg(*args, **kw):
print(args)
p1=functools.partial(showarg, 1,2,3)
p1(a='python', b='itcast')
p2=functools.partial(showarg, a=3,b='linux')
p2(a='python', b='itcast')
使用装饰器时,有一些细节需要被注意。例如,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变)。
添加后由于函数名和函数的doc发生了改变,对测试结果有一些影响,例如:
def note(func):
"note function"
def wrapper():
"wrapper function"
print('note something')
return func()
return wrapper
def test():
"test function"
print('I am test')
print(test.__doc__)
note something
wrapper function
所以,Python的functools包中提供了一个叫wraps的装饰器来消除这样的副作用。例如:
import functools
def note(func):
"note function"
@functools.wraps(func)
def wrapper():
"wrapper function"
print('note something')
return func()
return wrapper
def test():
"test function"
print('I am test')
print(test.__doc__)
note something
test function
3.8. 模块进阶
Python有一套很有用的标准库(standard library)。标准库会随着Python解释器,一起安装在你的电脑中的。 &它是Python的一个组成部分。这些标准库是Python为你准备好的利器,可以让编程事半功倍。
常用标准库
内建函数默认加载
操作系统接口
Python自身的运行环境
常用的工具
编码和解码 JSON 对象
记录日志,调试
multiprocessing
日期和时间
生成随机数
字符串正则匹配
标准的 BSD Sockets API
文件和目录管理
基于文件通配符搜索
import hashlib
m = hashlib.md5()
m.update('itcast')
print m.hexdigest()
用于注册、登录….
import hashlib
import datetime
KEY_VALUE = 'Itcast'
now = datetime.datetime.now()
m = hashlib.md5()
str = '%s%s' % (KEY_VALUE,now.strftime("%Y%m%d"))
m.update(str.encode('utf-8'))
value = m.hexdigest()
print(value)
8ad2d682e3529dac50e586fee8dc05c0
更多标准库
http://python.usyiyi.cn/translate/python_352/library/index.html
常用扩展库
使用的是 urllib3,继承了urllib2的所有特性
基于http的高层库
beautifulsoup4
HTML/XML的解析器
分布式任务调度模块
Pillow(PIL)
xlsxwriter
仅写excle功能,支持xlsx
仅写excle功能,支持xls ,2013或更早版office
仅读excle功能
elasticsearch
全文搜索引擎
数据库连接库
mongoengine/pymongo
mongodbpython接口
matplotlib
numpy/scipy
django/tornado/flask
xml 转 dict
SimpleHTTPServer
简单地HTTP Server,不使用Web框架
基于协程的Python网络库
数据处理库
scikit-learn
机器学习库
就可以运行起来静态服务。平时用它预览和下载文件太方便了。
在终端中输入命令:
python -m SimpleHTTPServer PORT
python -m http.server PORT
读写excel文件
1.安装个easy_install工具
sudo apt-get install python-setuptools
2.安装模块
sudo easy_install xlrd
sudo easy_install xlwt
matplotlib
pdb是基于命令行的调试工具,非常类似gnu的gdb(调试c/c++)。
继续执行程序
查看当前行的代码段
执行代码直到从当前函数返回
中止并退出
执行下一行
打印变量的值
查看传入参数
重复上一条命令
显示所有断点
break lineno
在指定行设置断点
break file:lineno
b file:lineno
在指定文件的行设置断点
删除指定断点
查看函数调用栈帧
执行时调试
程序启动,停止在第一行等待单步调试。
python -m pdb some.py
进入python或ipython解释器
import pdb
pdb.run('testfun(args)')
程序里埋点
当程序执行到pdb.set_trace() 位置时停下来调试
代码上下文
import pdb
pdb.set_trace()
print大法好
使用pdb调试的5个demo
import pdb
pdb.set_trace()
final = a + b + c
print final
import pdb
pdb.set_trace()
pdb.set_trace()
final = a + b + c
print final
import pdb
def combine(s1,s2):
s3 = s1 + s2 + s1
s3 = '"' + s3 +'"'
pdb.set_trace()
final = combine(a,b)
print final
In [1]: def pdb_test(arg):
for i in range(arg):
return arg
In [4]: import pdb
In [5]: pdb.run("pdb_test(10)")
& &string&(1)&module&()
& &ipython-input-1-ef4d08b8cc81&(1)pdb_test()
-& def pdb_test(arg):
def pdb_test(arg):
for i in range(arg):
return arg
& &ipython-input-1-ef4d08b8cc81&(2)pdb_test()
-& for i in range(arg):
def pdb_test(arg):
for i in range(arg):
return arg
& &ipython-input-1-ef4d08b8cc81&(3)pdb_test()
-& print(i)
& &ipython-input-1-ef4d08b8cc81&(2)pdb_test()
-& for i in range(arg):
& &ipython-input-1-ef4d08b8cc81&(3)pdb_test()
-& print(i)
& &ipython-input-1-ef4d08b8cc81&(2)pdb_test()
-& for i in range(arg):
demo 5 运行过程中使用pdb修改变量的值
In [7]: pdb.run("pdb_test(1)")
& &string&(1)&module&()
& &ipython-input-1-ef4d08b8cc81&(1)pdb_test()
-& def pdb_test(arg):
def pdb_test(arg):
for i in range(arg):
return arg
(Pdb) !arg = 100
& &ipython-input-1-ef4d08b8cc81&(2)pdb_test()
-& for i in range(arg):
def pdb_test(arg):
for i in range(arg):
return arg
(Pdb) p arg
练一练:请使用所学的pdb调试技巧对其进行调试出bug
import pdb
def add3Nums(a1,a2,a3):
result = a1+a2+a3
return result
def get3NumsAvarage(s1,s2):
s3 = s1 + s2 + s1
result = 0
result = add3Nums(s1,s2,s3)/3
if __name__ == '__main__':
final = get&3NumsAvarage(a,b)&
print final&
pdb 调试有个明显的缺陷就是对于多线程,远程调试等支持得不够好,同时没有较为直观的界面显示,不太适合大型的 python 项目。而在较大的 &python 项目中,这些调试需求比较常见,因此需要使用更为高级的调试工具。
3.10. 编码风格
这很浪费时间
我是个艺术家
所有人都能穿的鞋不会合任何人的脚
我善长制定编码规范
促进团队合作
减少bug处理
提高可读性,降低维护成本
有助于代码审查
养成习惯,有助于程序员自身的成长
pep8 编码规范
Python Enhancement Proposals :python改进方案
pep8 官网规范地址
Guido的关键点之一是:代码更多是用来读而不是写。编码规范旨在改善Python代码的可读性。
风格指南强调一致性。项目、模块或函数保持一致都很重要。
1.每级缩进用4个空格
括号中使用垂直隐式缩进或使用悬挂缩进。后者应该注意第一行要没有参数,后续行要有缩进。
foo = long_function_name(var_one, var_two,
var_three, var_four)
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
foo = long_function_name(
var_one, var_two,
var_three, var_four)
foo = long_function_name(var_one, var_two,
var_three, var_four)
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
2.四个空格的规则是对续行可选的
foo = long_function&_name(&
var_one, var_two,&
var_three, var_four)&
if语句跨行时,两个字符关键字(比如if)&加上一个空格,再加上左括号构成了很好的缩进。后续行暂时没有规定,至少有如下三种格式,建议使用第3种。
if (this_is_one_thing and
that_is_another_thing):
do_something()
if (this_is_one_thing and
that_is_another_thing):
do_something()
if (this_is_one_thing
and that_is_another_thing):
do_something()
2.右边括号也可以另起一行。有两种格式,建议第2种
my_list = [
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
my_list = [
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
4.空格或Tab?
空格是首选的缩进方法。
Tab仅仅在已经使用tab缩进的代码中为了保持一致性而使用。
Python 3中不允许混合使用Tab和空格缩进。
Python 2的包含空格与Tab和空格缩进的应该全部转为空格缩进。
5.最大行宽
限制所有行的最大行宽为79字符。
文本长块,比如文档字符串或注释,行长度应限制为72个字符。
两行空行分割顶层函数和类的定义。
类的方法定义用单个空行分割。
额外的空行可以必要的时候用于分割不同的函数组,但是要尽量节约使用。
额外的空行可以必要的时候在函数中用于分割不同的逻辑块,但是要尽量节约使用。
7.源文件编码
在核心Python发布的代码应该总是使用UTF-8(ASCII在Python 2)。
Python 3(默认UTF-8)不应有编码声明。
8.导入在单独行
import sys
from subprocess import Popen, PIPE
import sys, os
导入始终在文件的顶部,在模块注释和文档字符串之后,在模块全局变量和常量之前。
导入顺序如下:标准库进口,相关的第三方库,本地库。各组的导入之间要有空行。
9.禁止使用通配符导入
通配符导入(from import *)应该避免,因为它不清楚命名空间有哪些名称存,混淆读者和许多自动化的工具。
10.字符串引用
Python中单引号字符串和双引号字符串都是相同的。注意尽量避免在字符串中的反斜杠以提高可读性。
根据PEP 257, 三个引号都使用双引号。
11.括号里边避免空格
spam(ham[1], {eggs: 2})
spam( ham[ 1 ], { eggs: 2 } )
12.逗号,冒号,分号之前避免空格
if x == 4: print x, x, y = y, x
if x == 4 : print x , x , y = y , x
13.索引操作中的冒号当作操作符处理前后要有同样的空格(一个空格或者没有空格,个人建议是没有。)
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]
14.函数调用的左括号之前不能有空格
dct['key'] = lst[index]
dct ['key'] = lst [index]
15.赋值等操作符前后不能因为对齐而添加多个空格
long_variable = 3
long_variable = 3
16.二元运算符两边放置一个空格
涉及 =、符合操作符 ( += , -=等)、比较( == , & , & , != , && , &= , &= , in , not in , is , is not )、布尔( and , or , not )。
优先级高的运算符或操作符的前后不建议有空格。
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
17.关键字参数和默认值参数的前后不要加空格
def complex(real, imag=0.0):
return magic(r=real, i=imag)
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
18.通常不推荐复合语句(Compound statements: 多条语句写在同一行)
if foo == 'blah':
do_blah_thing()
do_three()
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
19.尽管有时可以在if/for/while 的同一行跟一小段代码,但绝不要跟多个子句,并尽量避免换行
if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t & 10: t = delay()
if foo == 'blah': do_blah_thing()
else: do_non_blah_thing()
try: something()
finally: cleanup()
do_one(); do_two(); do_three(long, argument,
list, like, this)
if foo == 'blah': one(); two(); three()
20.避免采用的名字
决不要用字符'l'(小写字母el),'O'(大写字母oh),或 'I'(大写字母eye) &作为单个字符的变量名。一些字体中,这些字符不能与数字1和0区别。用'L' 代替'l'时。
21.包和模块名
模块名要简短,全部用小写字母,可使用下划线以提高可读性。包名和模块名类似,但不推荐使用下划线。
2017 Python最新面试题及答案16道题
1.Python是如何进行内存管理的?
答:从三个方面来说,一对象的引用计数机制,二垃圾回收机制,三内存池机制
一、对象的引用计数机制
Python内部使用引用计数,来保持追踪内存中...
python基础 之 对象销毁(垃圾回收)
Python 使用了引用计数这一简单技术来跟踪和回收垃圾。
在 Python 内部记录着所有使用中的对象各有多少引用。
一个内部跟踪变量,称为一个引用计数器。
当对象被创建时, 就创建了一个引用...
python面试题(持续)
python语言特性(数据结构、语法结构)
1. range和xrange
python2.x中,range和xrange有什么区别?
for i in range(0, 20)
Python内存管理及释放
python话说会自己管理内存,实际上,对于占用很大内存的对象,并不会马上释放。举例,a=range(),会发现内存飙升一个多G,del a 或者a=[]都不能将内存降下来。。
...
精心整理的8道Python面试题
NO.1Python这么好说说它的特性吧关键特性Python是一种解释型语言,这意味着,与C,C++不同,Python不需要在运行之前进行编译。它是边运行边解释。Python是动态类型化的,这意味着当...
python常见知识点整理
Python是一个面向对象的解释型的交互式高级脚本语言:Python被设计成一种高可读性的语言,因为它大量地使用了英语中的单词作为关键字,而且不像其他语言使用标点符号构成复杂的语法结构,Python的...
python高级2:其他知识点1
第二章 其他的知识点
2.1. import导入模块
2.2. 循环导入
2.3. 作用域
2.4. ==、is
2.5. 深拷贝、浅拷贝
2.6. 进制、位运算
2.7. 私有化
2.8. 属性...
Python 知识点整理
一.from os import makedirs, unlink, sep
#从os包中引入 makedirs.unlink,sep类from os.path import dirname, e...
python高级知识点总结(一)
一、什么是视图? -- 通俗的讲,视图就是一条SELECT语句执行后返回的结果集。 -- 所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。 -- 视图的特点 -- 视图是对若干张基...
python的学习知识点总结
建议遵守以下约定:使用 4 个空格来缩进
永远不要混用空格和制表符
在函数之间空一行
在类之间空两行
字典,列表,元组以及参数列表中,在 , 后添加一个空格。对于字典,: 后面也添加一个空格 ...
没有更多推荐了,}

我要回帖

更多关于 python两个冒号 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信