您的位置:首页 > 编程语言 > Python开发

Python基础--第3章 语言规则——Python的条条框框

2018-03-07 09:45 323 查看
本章将从剖析编程语言的角度开始介绍Python语言类型,并学习基础的编程规则与代码文件的结构。
 

3.1  编程语言类型

计算机发展到今天,关于编程的语言已经是五花八门。在这么多语言中Python是个什么状态呢?为了更形象的了解Python语言及特性。下面就通过对各个角度的分析比较Python与其他语言的区别。业界关于编程语言的分类有很多维度,有的从运行角度、有的从形态角度等,具体分析如下。

3.1.1  运行角度的编程语言分类

从运行角度来看,编程语言的类型可以分为两种:编译型和解释型。各自的意义如下:
l  编译型语言:代码本身不能运行,需要一个附加程序(编译器)将其转换成由二进制代码组成的可执行文件,然后才可以运行。例如:C/C++、Pascal/Object   Pascal(Delphi)、VB等基本都可视为编译语言;
l  解释型语言:代码可以直接运行,当然同样也是依赖于附加程序(解释器)来实现的。解释器会不断的循环一组动作:取一行源程序;将其转成二进制指令;然后执行。这样一直下去,直到全部的源程序读取完毕。例如:Java、JavaScript、VBScript、Perl、Python属于解释型语言。
二者最大的区别就是,编译型语言生成完可执行程序后,就可以独立执行了。而解释性语言必须依赖于解释器才可以执行。当然也有些附属的打包程序,可以将解释性语言打包成为独立执行的程序,但总体来讲效率及性能会略慢于编译型语言生成的程序。

3.1.2  形态角度的编程语言分类

从形态角度来看,编程语言的类型可以分为两种:动态语言和静态语言。各自的意义如下:
l  动态语言:常用语解释型语言,程序运行时才去做数据类型的检查,即,定义变量时不需要指定数据类型,只有在第一次给变量赋值时,根据赋值的类型来内部指定该变量的类型。如:Python、ruby语言;
l  静态语言:常用语编译型语言,即,编译时要检查数据的类型。即,在使用变量之前必须要定义好类型。如:C、C++、 C#、JAVA等。

3.1.3  语义角度的编程语言分类

从语义角度来看,编程语言的类型可以分为两种:强定义类型和弱定义类型。各自的意义如下:
l  强定义类型语言:具有严格的类型区分,变量一旦被指定所属的数据类型之后必须经过转换才能存取为别的类型。如:c、java、Python等;
l  弱定义类型语言:类型不严格区分,一般是只要大小放得下,就可以转化。这种是汇编级的观点。如:VBScript
综上所述:Python是一门动态解释性的强定义类型语言。其优点是代码简洁、可读性强、开发效率比较高、可移植性好、可拓展性好、可嵌入性好;缺点是运行时的性能相对较低、源代码不能加密。
 

3.2基础规则

对于一个Python项目,它的代码部署路径与代码内容也是息息相关的,这里面涉及到有代码文件、模块、包的相关概念及使用规则。具体如下:
 

3.2.1  代码文件及模块

Python程序由代码块构成,代码块可以理解成为一个容器,里面放置一条一条的语句。一个模块文件、一个函数体、一个类、交互式命令中的单行代码都叫做一个代码块。
模块文件是指封装好的代码文件,做为独立的模块来被其他程序引用。
函数是指在一个代码文件中,将若干条语句封装在一个代码块里完成某个独立的功能,供其他程序使用。
类是指以面向对象思想将变量及函数封装成具有某个类别特性的结构体,它可以是以模块文件的形式单独提供,也可以与本地程序一起放在相同代码文件中。
 

3.2.2  语句规则

Python的运行是在Python解释器中来实现的,错误的Python语句将不能被解释器所执行。具体的语句规则如下:
l 变量的命名:可以使用字符数字和下划线的组合,首字母可以是字母或者下划线;
l 语句区分:在Python解释器中,对源代码是一行一行解释执行的,行与行之间通过换行符号来区分,默认是一行一条语句,如果在一行中放有多条语句可以通过“;”来区分;
l 代码块:通过缩进来表述代码块的概念,即同一个代码块中的语句具有相同的缩进格式。缩进可以是空格或是tab键。以如下代码举例:
deffun():         #定一个函数名字叫做fun
  print(“hello fun”) #该语句被缩进,表示fun函数的函数体,只有执行函数fun时才被执行
print(“hellomain”)  #该语句没被缩进,直接执行
fun()             #该语句没被缩进,会执行其函数体内的语句
变量命名的好习惯:禁用0oO1lL。

3.2.3  注释方法

英文字符“#”来代表注释的意思。它的生效范围是行,即在一行中#之后的内容将不被Python解释器处理。
注释的用途一般是用来说明代码的具体含义,方便开发人员阅读。另外也可以用来控制程序暂时不执行某一部分的代码块。
在spyder中可以使用如下操作快速成块添加或删除注释。

3.2.4  Python帮助

在Python中使用help来获取帮助信息。它可以查找关于Python的基础函数、类型、常用库等信息。
例如:help(print)

3.3  代码文件结构

Python的文件结构可以分为包、模块、代码。代码是组成程序的基本单位,是一条一条的具体语句。代码的载体是文件。Python中的代码文件是以.py 结尾的。

3.3.1  模块

当实现一个复杂程序时,往往需要编写很庞大的代码量。这时就需要将一个代码文件分割成多个代码文件,每个文件上放置具有相对独立功能的代码。同时多个文件中的代码能够被导入到当前代码文件中来,实现完整的功能。这就是模块(module)。
概括的说,模块就是一个个支持导入功能的,以.py 结尾的代码文件。

3.3.2  包

当模块足够庞大时,维护起来也是不方便的事情。这就需要使用包(Package)的概念了。包可以把多个模块(.py文件),放在同一个文件夹中。来归类管理。
概括的说,包就是放置模块的文件夹。例如,下面代码是一个名字为CycleGAN对抗神经网络的目录:
CycleGAN/                       #顶级包 
      __init__.py                    
         main.py
      sampel/                     #样本处理子包 
              __init__.py 
              Download_data.py 
              build_data.py 
             
      model/                      #模型子包 
              __init__.py 
              discriminator.py 
              generator.py
             
      work/                                  #协调工作子包 
              __init__.py 
              train.py 
              export_graph.py
              eval.py 
在上面的目录结构中,顶级包CycleGAN下面分为样本处理子包、模型子包和协调工作子包。每个子包里有放有功能大致雷同的模块。比如模型子包里面放的模块都是关于各种模型的代码:
l 判别器模块(discriminator.py),实现了一个判别器模型;
l 生成器模块(generator.py)实现了一个生成器模型。
注意:在每个包文件夹里都必须包含一个 __init__.py 的文件,告诉Python,该文件夹是一个包。__init__.py 可以是一个空文件。
 

3.4  模块的详细介绍

Python 模块(Module)包含了 Python 对象定义和Python语句。在模块里,可以定义函数、类和变量。模块也能包含可执行的代码。
把相关的代码分配到一个模块里,可以使代码更好用,更易懂。养成使用模块的习惯可以使开发者能够有逻辑地组织自己的Python 代码段。

3.4.1  模块的作用及分类

模块的主要作用是用来导入到其他代码模块中。将其他模块导入(import)到当前模块,可以理解成是对当前模块功能增强的一种拓展。
不同模块中的函数名和变量是可以相同的。模块的使用可以避免在庞大代码量中,函数名和变量名冲突的问题。另外,将代码模块化也提高了代码的可维护性与重用性。
Python中的模块可以分为内置模块、自定义模块和第三方模块三类:
l 内置模块:Python中本来就有的模块;
l 自定义模块:自己开发的模块;
l 第三方模块:需要单独下载安装,并导入的模块。

3.4.2  模块的基本使用

模块使用起来非常简单,只需要用关键字import后面加上模块名字即可将模块导入进来。下面举例引入一个内置的time模块,显示当前时间:
importtime                                                             #引入time模块
print(time.time())                                                   #获取当前时间,输出:1513299326.049188
print(time.localtime( time.time() ) .tm_year)   #将当前时间格式化,输出:2018
对于内置模块和已经安装好的第三方模块,系统会自动在内置或已经配置好的模块路径下查找该模块,并载入。
 

3.4.3  模块搜索路径

对于自定义模块还要考虑到自己模块所在的位置,要配合包名一起引入。具体写法是:
import包名.模块名
例如,在3.3.2目录结构的例子中,想要在main.py中导入work下面的train.py模块。需要如下写法:
importwork.train
当导入名为 train 的模块时, 解释器会先从内置模块尝试匹配。如果没找到,则将在 sys.path 记录的所有目录中搜索train.py 文件。变量 sys.path 是一个字符串列表,它为解释器指定了模块的搜索路径。sys.path包括:
l 当前程序所在目录;
l 标准库的安装目录(例如:pythom35\\lib\\site-packages);
l 操作系统环境变量PythonPATH所包含的目录。
在编写代码时,也可以通过列表操作来对sys.path进行读写,例如:
importsys                                                              #引入sys库
print(sys.path)                                                      #将sys.path打印出来
sys.path.append('d://lib//Python')            #在sys.path里添加一条路径
通过代码对sys.path修改,可以减小Python程序对环境的依赖,为部署提供了便利。
对sys.path的修改只是在本次程序内有效。系统并不会将sys.path持久化保存。要想永久生效还需要在环境变量里配置。
 

3.4.4  模块属性

模块除了被引用以外,还会有自己的属性可供调用者查看。其属性大致有如下几种:
l __name__:名字;
l __doc__:详细说明,介绍了该模块的使用方法;
l __package__:所在的包名;
l __loader__:加载的类名;
l __spec__:简介,介绍了该模块的名字、加载类名、来源类型等概要信息。
要想查看这些属性的内容。可以通过导入的模块名后面加个点,再跟上具体的属性变量即可,例如:
importtime                                 #引入time模块
print(time.__name__)         #模块名字。输出:time
print(time.__doc__)                            #详细说明。输出:This module provides various...
print(time.__package__)                   #包名。因为是内置模块,包名为空,所以输出为空。
print(time.__loader__)              #加载的类名。输出:<class '_frozen_importlib.BuiltinImporter'>
print(time.__spec__)               #简介。输出:ModuleSpec(name='time', ...

3.4.5  模块名字的可变性

在Python中,模块的名字属性还会根据不同的使用场景发生变化。当模块被导入到其他模块时,__name__的值为模块本身的名字;而当该模块自己独立运行时,__name__的值会变为“__main__”。例如:
(1)新建一个test1.py文件,写入如下代码:
print(__name__)         #将当前模块的名称打印出来
(2)再新建一个test2.py文件,写入如下代码:
importtest1                       #导入test1模块
(3)运行test1.py文件,输出如下:
__main__                          #输出模块名
(4)运行test2.py文件,输出如下:
test1                                    #输出模块名
可以看到虽然是同样一段代码。在第三步中是直接运行,输出了模块名字为“__main__”,在第四步是通过import导入运行的,输出的模块名字就变为了“test1”。
 

3.4.6  模块的常规写法

Python程序中每个代码文件在可以独立运行的同时,也可以作为一个模块文件。编写模块文件的好的习惯是,在编写该模块提供的函数或类的同时,也可以把自身当作独立运行的文件来为自身模块做单元测试。
这就需要借助模块名字属性可变的特性来实现了。例如,可以在模块的最下面加入名字的判断,并执行单元测试代码:
if__name__ == '__main__':
                 执行单元测试代码
这样当直接运行这个模块文件的时候,可以通过测试代码来检验所定义的函数的输入和输出是否正确。而引入模块时,测试代码有不会被执行。为模块编写对应的单元测试代码是一个非常好的编程习惯。
 

3.5  模块的几种导入方式

下面介绍几种Python导入模块的方法。

3.5.1  import  as方式

import as的方式其实是实现了两步操作,先将模块导入,再为模块重命名。其写法如下:
importa as b
其中a代表要引入的模块。B为将a重命名后的名称。即,导入将模块a,并将其重命名为b。举例,如下:
importtime as x                            #导入模块time并将其重命名为x
s= x.ctime()                                       #调用模块time中的ctime函数。得到当前时间
print(s)                                                #将时间输出:Thu Mar  1 14:59:17 2018
例子中把引入的time模块重命名为x。后面就可以使用x来当作time模块,并调用其ctime的方法获得了当前时间。

3.5.2  from   import方式

from import的方式是直接把模块内的函数或变量的名称导入当前模块。其写法如下:
froma import func
代表将模块a中的func函数导入到当前模块。当使用了这种写法进行导入时,当前模块将只能使用a中的func函数,无法使用a中的其他函数。例如:
fromtime import ctime  #导入模块time中的ctime函数
s= ctime()                      #直接调用函数 
print(s)                              #将时间输出:Thu Mar  1 14:59:17 2018
例子中把引入了time模块中的ctime函数。后面就可以直接使用ctime函数来获得时间。
如果再想调用time模块中的其他函数,将会获得失败。例如,接上面代码,添加如下语句
print(time.time())
运行的时候,程序会报错。显示如下:
NameError:name 'time' is not defined
因为程序只引入了ctime函数。并不知道time模块,所以提示time没定义。

3.5.3  from   import*方式

from import *的方式将模块中所有的名字(以下划线开头的名字除外)导入到当前模块符号表里。具体代码如下:
fromtime import *        #导入模块time中的所有名字(以下划线开头除外)
s= ctime()                    #直接调用函数
print(s)                              #将时间输出:Thu Mar  1 14:59:17 2018
这时在运行time中的time函数就不会报错了。代码如下:
print(time())                      #返回当前时间的时间戳(1970纪元后经过的浮点秒数)输出:1519889455.5011432
使用该方式导入模块的好处是方便。弊端是容易产生名字冲突(如果当前模块里也有个ctime函数,就会跟导入的ctime发生名字冲突)。这是需要注意的地方。

3.5.4  导入带空格名字的模块

在3.3.1中讲过,模块的即是一个代码文件。而代码文件的命名规范是符合操作系统的命名规则的。在操作系统中会允许文件名中出现空格。但这个规则与Python语法发生冲突,因为在Python中,是以空格来隔离一行语句中的不同元素的。在这种情况下,导入带空格的模型势必带来了麻烦。
解决办法是使用__import__方法。例如假设有个模块叫做“9-24  yuyinutils”,要在当前文件引入它时,可以写成如下样子:
 yuyinutils = __import__("9-24  yuyinutils")
通过使用__import__方法。将模块名称用字符串的方式传入,就可以使用其返回值当成该模块来使用了。
注意:
该部分代码来自于《深度学习之TensorFlow入门原理与进阶实战》 一书中语音识别的案例9-23  yuyinchall.py代码文件中的开头部分。如何将__import__的返回值当作模块使用,可以参考这部分代码的详细演示。
 

3.5  常用模块

在Python中还有好多有用的内置模块。例如下面的代码,使用platform 获得系统版本:
importplatform 
s= platform.platform()
print(s)                      #输出:Windows-7-6.1.7601-SP1
当不熟悉某个模块的内容时,还可以使用dir来列出该模块的内容,例如:
importplatform 
dir(platform)                      #使用dir命令查询platform内容
下面简单的介绍几个常用模块即简单用法:
表3-1  常用的模块及用法
[align=center]
模块
函数即用法
描述
os
用于调用系统命令等
os.path
打印当前路所在的路径
os.system("dir")
执行系统的dir命令,成功:返回0
os.mkdir("mydir")
失败:返回非0
os.rmdir("mydir")
执行在当前路径下创建文件夹mydir
Print(os.popen("ipconfig").read())
执行在当前路径下删除mydir文件夹
sys
sys.path
Python的安装路径
sys.argv
取得程序在命令行方式运行下的输入参数。如:print(sys.argv[0])输出第一个参数
[/align] 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Python基础