码迷,mamicode.com
首页 > 编程语言 > 详细

03 Python 基础 - 《Python 核心编程》

时间:2015-08-13 21:54:45      阅读:244      评论:0      收藏:0      [点我收藏+]

标签:

?? 语句和语法
?? 变量赋值
?? 标识符和关键字
?? 基本风格指南
?? 内存管理
?? 第一个 Python 程序
3.1语句和语法
Python 语句中有一些基本规则和特殊字符:
    ?? 井号(#)表示之后的字符为 Python 注释
    ?? 换行 (\n) 是标准的行分隔符(通常一个语句一行)
    ?? 反斜线 ( \ ) 继续上一行
    ?? 分号 ( ; )将两个语句连接在一行中
    ?? 冒号 ( : ) 将代码块的头和体分开
    ?? 语句(代码块)用缩进块的方式体现 (缩进四个空格宽度,避免使用制表符)
    ?? 不同的缩进深度分隔不同的代码块
    ?? Python 文件以模块的形式组织 (当一个模块变得过大,并且驱动了太多功能的话,就应该考虑拆一些代码出来另外建一个模块.)
注释( # )
    和很多 Unix 脚本类似,Python 注释语句从 # 字符开始,注释可以在一行 的任何地方开始,解释器会忽略掉该行 # 之后的所有内容。要正确的使用注释。
继续( \ )
    Python 语句,一般使用换行分隔,也就是说一行一个语句。一行过长的语句可以使用反斜 杠( \ ) 分解成几行,如下例:
        # check conditions
        if (weather_is_hot == 1) and \
        (shark_warnings == 0):
            send_goto_beach_mesg_to_pager()
    有两种例外情况一个语句不使用反斜线也可以跨行。
        在使用闭合操作符时,单一语句可以 跨多行,例如:在含有小括号、中括号、花括号时可以多行书写。
        另外就是三引号包括下的字符串也可以跨行书写。
    如果要在使用反斜线换行和使用括号元素换行作一个选择,我们推荐使用括号,这样可读 性会更好。
多个语句构成代码组(:):
    缩进相同的一组语句构成一个代码块,我们称之代码组。
    像if、while、def 和class 这样 的复合语句,首行以关键字开始,以冒号( : )结束,该行之后的一行或多行代码构成代码组。我们将首行及后面的代码组称为一个子句(clause)。
代码组由不同的缩进分隔
    代码的层次关系是通过同样 深度的空格或制表符缩进体现的。
    核心风格:缩进四个空格宽度,避免使用制表符 
        对一个初次使用空白字符作为代码块分界的人来说,遇到的第一个问题是:缩进多大宽度 才合适?两个太少,六到八个又太多,因此我们推荐使用四个空格宽度。
        需要说明一点,不同的文本编辑器中制表符代表的空白宽度不一,如果你的代码要跨平台应用,或者会被不同的编辑器读写,建议你不要使用制表符。
        使用空格或制表符这两种风格都得到了Python 创始人Guido  van Rossum 的支持,并被收录到Python 代码风格指南文档。
同一行书写多个语句(;)
    分号( ; )允许你将多个语句写在同一行上,语句之间用分号隔开,而这些语句也不能在这 行开始一个新的代码块。
    必须指出一点, 同一行上书写多个语句会大大降低代码的可读性,Python 虽然允许但不 提倡你这么做。
模块
    每一个Python 脚本文件都可以被当成是一个模块。模块以磁盘文件的形式存在。当一个模 块变得过大,并且驱动了太多功能的话,就应该考虑拆一些代码出来另外建一个模块。
    模块里的代码可以是一段直接执行的脚本,也可以是一堆类似库函数的代码,从而可以被别的模块导入(import)调用。
    模块可以包含直接运行的代码块、类定义、函数定义或这几者的组合。

3.2 变量赋值

赋值运算符
    Python 语言中, 等号(=)是主要的赋值运算符。
    注意,赋值并不是直接将一个值赋给一个变量, 尽管你可能根据其它语言编程经验认为应该如此。在Python 语言中,对象是通过引用传递的。在赋值时,不管这个对象是新创建的,还是一个已经存在的,都是将该对象的引用(并不是值)赋值给变量。同样的, 如果你比较熟悉C, 你会知道赋值语句其实是被当成一个表达式(可以返回值)。不过这条并不适合于 Python, Python 的赋值语句不会返回值。
链式赋值
>>> y = x = x + 1
>>> x, y
(2, 2)
增量赋值
>>> x = 1
>>> x += 1
>>> x
2

多元赋值 (采用这种方式赋值时, 等号两边的对象都是元组)

>>> x, y, z = 1, 2, ‘a string‘
>>> x
1
>>> y
2
>>> z
‘a string‘
Python 的多元赋值方式可以实现无需中间变量交换两个变量的值。

3.3 标识符

合法的Python 标识符
    Python 标识符字符串规则和其他大部分用C 编写的高级语言相似:
        ?? 第一个字符必须是字母或下划线(_)
        ?? 剩下的字符可以是字母和数字或下划线
        ?? 大小写敏感
关键字
技术分享

内建

    除了关键字之外,Python 还有可以在任何一级代码使用的“内建”的名字集合,这些名字 可以由解释器设置或使用。
    虽然built-in 不是关键字,但是应该把它当作“系统保留字”,不做他用。
        然而,有些情况要求覆盖(也就是:重定义,替换)它们。
    Python 不支持重载标识符,所以任何时刻都只有一个名字绑定。 
    我们还可以告诉高级读者built-in 是__builtins__模块的成员,在你的程序开始或在交互 解释器中给出>>>提示之前,由解释器自动导入的。
    把它们看成适用在任何一级Python 代码的全局变量。
专用下划线标识符
    Python 用下划线作为变量前缀和后缀指定特殊变量。
总结:
?? _xxx 不用‘from module import *‘导入
?? __xxx__系统定义名字
?? __xxx 类中的私有变量名
    核心风格:避免用下划线作为变量名的开始
        因为下划线对解释器有特殊的意义,而且是内建标识符所使用的符号,我们建议程序员避免用下划线作为变量名的开始。
        一般来讲,变量名_xxx 被看作是“私有的”,在模块或类外不可以使用。
        当变量是私有的时候,用_xxx 来表示变量是很好的习惯。因为变量名__xxx__对Python 来说有特殊含义,对于普通的变量应当避免这种命名风格。
3.4 基本风格指南
    注释,文档,缩进,标识符
    模块结构和布局
        # (1) 起始行(Unix)
        # (2) 模块文档
        # (3) 模块导入
        # (4) 变量定义
        # (5) 类定义
        # (6) 函数定义
        # (7) 主程序
        (1) 起始行
            通常只有在类Unix 环境下才使用起始行,有起始行就能够仅输入脚本名字来执行脚本,无
        需直接调用解释器。
        (2)模块文档
            简要介绍模块的功能及重要全局变量的含义,模块外可通过 module.__doc__ 访问这些内 容。 
        (3)模块导入
            导入当前模块的代码需要的所有模块;每个模块仅导入一次(当前模块被加载时);函数内部的模块导入代码不会被执行, 除非该函数正在执行。 
        (4)变量定义
            这里定义的变量为全局变量,本模块中的所有函数都可直接使用。
            从好的编程风格角度说, 除非必须,否则就要尽量使用局部变量代替全局变量,如果坚持这样做,你的代码就不但容易维护,而且还可以提高性能并节省内存。 
        (5)类定义语句
            所有的类都需要在这里定义。当模块被导入时class 语句会被执行, 类也就会被定义。类的文档变量是class.__doc__。 
        (6)函数定义语句
            此处定义的函数可以通过module.function()在外部被访问到,当模块被导入时 def 语句会被执行,函数也就都会定义好,函数的文档变量是function.__doc__。 
        (7) 主程序
            无论这个模块是被别的模块导入还是作为脚本直接执行,都会执行这部分代码。通常这里 不会有太多功能性代码,而是根据执行的模式调用不同的函数。
 
        技术分享
                Figure 3–1 Typical Python file structure
    推荐代码风格:主程序调用main()函数 
        主程序代码通常都和你前面看到的代码相似,检查 __name__ 变量的值然后再执行相应的 调用(参阅下一页的核心笔记)。
        主程序中的代码通常包括变量赋值, 类定义和函数定义,随后检查__name__来决定是否调用另一个函数(通常调用main()函数)来完成该模块的功能。    
        主程序通常都是做这些事。(我们上面的例子中使用test()而不是main()是为了避免你在读到核心笔记前感到迷惑。) 
        不管用什么名字,我们想强调一点那就是:这儿是放置测试代码的好地方。大部分的Python 模块都是用于导入调用的,直接运行模块应该调用该模块的回归测试代码。
        请记住,绝大部分的模块创建 的目的是为了被别人调用而不是作为独立执行的脚本。
        只有一个模块,也就是包含主程 序的模块会被直接执行,或由用户通过命令行执行,或作为批处理执行, 或由Unix cron 任务定时执行,或通过Web 服务器调用,或通过GUI 执行。
    核心笔记:__name__ 指示模块应如何被加载
        如果模块是被导入, __name__ 的值为模块名字 
        如果模块是被直接执行, __name__ 的值为 ‘__main__‘
3.5 内存管理
?? 变量无须事先声明
?? 变量无须指定类型
?? 程序员不用关心内存管理
?? 变量名会被“回收”
?? del 语句能够直接释放资源
变量定义
    在Python 中,无需显式变量声明语句,变量在第一次被赋值时自动声明。
    和其他大多数语言一样,变量只有被创建和赋值后才能被使用。
动态类型
    Python 中不但变量名无需事先声明,而且也无需类型声明。
    Python 语言中, 对象的类型和内存占用都是运行时确定的。
    尽管代码被编译成字节码,Python 仍然是一种解释型语言。
    在创建--也就是赋值时,解释器会根据语法和右侧的操作数来决定新对象的类型。
    在对象创建后,一个该对象的引用会被赋值给左侧的变量。
内存分配
    作为一个负责任的程序员,我们知道在为变量分配内存时,是在借用系统资源,在用完之 后, 应该释放借用的系统资源。
    Python 解释器承担了内存管理的复杂任务, 这大大简化了应用程序的编写。
    你只需要关心你要解决的问题,至于底层的事情放心交给Python 解释器去做就行了。
引用计数
    每个对象各有多少个引用, 简称引用计数。

    一个引用计数内部跟踪变量,称为一个引用计数器。

    当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0 时, 它被垃圾回收。
增加引用计数
    当对象被创建并(将其引用)赋值给变量时,该对象的引用计数就被设置为1。
    当同一个对象(的引用)又被赋值给其它变量时,
        或作为参数传递给函数, 方法或类实例 时,
        或者被赋值为一个窗口对象的成员时,该对象的一个新的引用,或者称作别名,就被创建(则该对象的引用计数自动加1)。
对象的引用计数在 
    ?? 对象被创建
        x = 3.14
    ?? 或另外的别名被创建
        y = x
    ?? 或被作为参数传递给函数(新的本地引用)
        foobar(x)
    ?? 或成为容器对象的一个元素
        myList = [123, x, ‘xyz‘]
减少引用计数
    当对象的引用被销毁时,引用计数会减小。
        最明显的例子就是当引用离开其作用范围时,这种情况最经常出现在函数运行结束时,所有局部变量都被自动销毁,对象的引用计数也就随之减少。
    当变量被赋值给另外一个对象时,原对象的引用计数也会自动减1:
        foo = ‘xyz‘   #‘xyz‘  1
        bar = foo     #‘xyz‘  2
        foo = 123    #‘xyz‘  1
    其它造成对象的引用计数减少的方式包括使用 del 语句删除一个变量(参阅下一节), 或 者当一个对象被移出一个窗口对象时(或该容器对象本身的引用计数变成了0 时)。
    一个对象的引用计数在以下情况会减少:
        ?? 一个本地引用离开了其作用范围。比如 foobar()(参见上一下例子)函数结束时。
        ?? 对象的别名被显式的销毁。
            del y # or del x
                ?? 从现在的名字空间中删除 y
                ?? x 的引用计数减一
        ?? 对象的一个别名被赋值给其它的对象
            x = 123
        ?? 对象被从一个窗口对象中移除
            myList.remove(x)
        ?? 窗口对象本身被销毁
            del myList # or goes out-of-scope
垃圾收集
    不再被使用的内存会被一种称为垃圾收集的机制释放。
    虽然解释器跟踪对象 的引用计数, 但垃圾收集器负责释放内存。
    垃圾收集器是一块独立代码, 它用来寻找引用计数为0 的对象。
        它也负责检查那些虽然引用计数大于0 但也应该被销毁的对象。 
        特定情形会导致循环引用。 
        一个循环引用发生在当你有至少两个对象互相引用时, 也就是说所有的引用都消失时, 这 些引用仍然存在, 这说明只靠引用计数是不够的。
    Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。
    当一个对象的引用计数变为0,解释器会暂停,释放掉这个对象和仅有这个对象可访问(可到达)的其它对象。
    作为引用计数的补充, 垃圾收集器也会留心被分配的总量很大(及未通过引用计数销毁的那些)的对象。
    在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环。
核心技巧:使用局部变量替换模块变量
    类似 os.linesep 这样的名字需要解释器做两次查询:
        (1)查找os 以确认它是一个模块,
        (2)在这个模块中查找 linesep 变量。因为模块也是全局变量, 我们多消耗了系统资源。
    如果你在一个函数中类似这样频繁使用一个属性,我们建议你为该属性取一个本地变量别名。
    变量查找速度将会快很多--在查找全局变量之前, 总是先查找本地变量。
    这也是一个让你的程序跑的更快的技巧: 将经常用到的模块属性替换为一个本地引用。代码跑得更快,而也不用老是敲那么长的变量名了。
3.6 相关模块和开发工具
    Python 代码风格指南(PEP8), Python 快速参考和Python 常见问答都是开发者很重要的“工具”。
    另外, 还有一些模块会帮助你成为一个优秀的Python 程序员。
?? Debugger: pdb
?? Logger: logging
?? Profilers: profile, hotshot, cProfile

03 Python 基础 - 《Python 核心编程》

标签:

原文地址:http://www.cnblogs.com/BugQiang/p/4728321.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!