在摸索适合自己的语言学习方法,看到一篇好文章,转之,侵删。

Python的语法范式相当多、知识点相当细,但是Python是一种内在一致性很好的语言,理解了几条基本的规则,就很容易理解大部分语法与现象。本文会总结一下Python中最根本的几条规则,从这几条规则中,我们可以看出Python与许多其他语言不同,它是非常纯粹、非常和谐的。

Python的基本语法:表达式运算与名称绑定

Python的语句大体上可以分成简单语句和复合语句两类,简单语句当中,最重要的是表达式语句和赋值语句。为了区分C/C++等其他语言当中的赋值,本文中,我们将

a = 1b= 'abc'c= (a,b)

这样的赋值语句称为名称绑定。顾名思义,它代表将右侧表达式运算的结果起了个名字,方便我们将来使用。相应的,变量在本文中称为名称,它主要代表名字本身,而不是对应的值。在官方文档当中叫做identifier(标识符),绑定也就是bound。

关于表达式、简单语句、复合语句的分类,在官方文档 https://docs.python.org/2.7/reference/index.html 当中已经讲得非常好而全面了(用Python 3的注意左上角切换版本)。简单来说,表达式有很多种,比如常量,比如单个名称,比如运算,比如调用,比如yield等等,这个列表也会不断扩展。表达式的共同特点是它们都有且仅有一个返回值——有些返回值永远是None,有些返回值是元组,但可以认为都是有且仅有一个返回值。

有些时候我们直接计算表达式就够了,比如有些函数调用。另一些时候,我们会关心这个表达式求出的值,我们希望在后面重新使用这个计算出的值,我们就用到了名称绑定,也就是为这个结果起一个方便我们后面使用的名字,通过名称绑定,它是非常浅显易懂的语法,通常由一个等号组成,等号左侧是要赋值的名称,右侧是表达式,表达式的结果就会绑定到这个名称上:

=

这种包含等号的语句叫做赋值语句,它还有另外几种变种:

, =

#如:

a,b = (1,2)#或者

a,b = 1,2

表示解构的赋值

= = = ... =

可以将同一个值绑定到多个名称。

赋值语句和名称绑定略有区别,它除了用于名称绑定以外,还可以用来修改可变对象如列表(list)和字典(dict):

a[1] = 2a[2:3] = [4,5,6]

b['a'] = 12

通常需要注意区别。

Python绑定 vs C赋值

我们看下面的代码:

a = 1a= "abc"

当我们对已经绑定了的名称重新赋值的时候,旧的值会解除绑定,新的值绑定到名称,这对于旧的值和新的值来说都是不可见的。名称相当于相应值的别名,这个值有多少个名称,都不会影响到值本身;同样,不同的名称也都代表同一个值,因此如果多个名称绑定到了同一个值,而值发生了变化,所有名称对应的值都会变化:

a = [1,2]

b=a

a.append(3)

a#[1,2,3]

b #[1,2,3]

以往会用“传值/传引用”、“强类型/弱类型”这样的概念,对于Python来说其实都是不必要的,我们记住这样的规则:名称只是对象的别名,不同的名称可以表示同一个对象,同一个对象并没有唯一的名称。

C中的变量就完全不一样,一旦定义就占用固定的内存,赋值实际上是实际内存值的复制。Python的名称是个逻辑概念,而C的变量相当贴近物理实现,这也体现了Python作为编程语言更为纯粹这一特点。

除了重新绑定时候自动解除旧值的绑定,Python中的名称还可以强制解除绑定:

del

特殊绑定

除了赋值语句以外,还有一些特殊语句会实现名称绑定,主要包括import、def(函数定义)、class(类定义)。此外,某些语句的主要功能不是名称绑定,但可以额外附加名称绑定的效果,如for、except、with。

重点说前三个,它们实际上都是赋值语句的直接变形,如import:

importmy_moduleimportmy_module as m1from my_module importmy_objectfrom my_module import my_object as o1

实际上完全等效于:

my_module = __import__('my_module')

m1= __import__('my_module')

_= __import__('my_module')

my_object=_.my_objectdel_

_= __import__('my_module')

o1=_.my_objectdel _

这些语句只是将表达式求值 + 赋值的过程写成了比较统一、简洁、易懂的形式,要理解它们本质上仍然是赋值语句。因此import的结果也可以用del解除绑定,可以重新绑定到新的值。这体现了Python语言的一致性。

定义函数和类也是这样:

defmy_func():pass

#重新绑定

my_func = 123

#解除绑定

del my_func

这与C/C++区别很大,它们都是在定义的时候创建了函数/类的对象,然后将这个对象绑定到了相应的名称上,理解这一点对于理解嵌套函数定义之类的规则大有帮助。

作用域,作用域嵌套与global作用域

在函数中,名称可以独立进行重新绑定,而不影响外部绑定的效果,这种特性叫做名称作用域:

a = 1

deffunc():

a= 2

returna

func()#2

a #1

每个函数都有自己独立的作用域,但与C/C++不同,复合语句没有自己独立的作用域。函数中可以嵌套定义其他函数,这些函数也有自己的作用域:

a = 1

deffunc1():

a= 2

deffunc2():

a= 3

returnareturn(a, func2())

func1()#(2,3)

a #1

最外层的作用域叫做global作用域,对于一个最外层的函数来说,这是这个函数定义的模块。

名称可以同时存在在多个不同的作用域中,在Python的函数中使用名称时,名称解析到具体哪一个作用域,服从下面的规则:

一旦这个函数中存在对某个名称的绑定,则在这个函数中,名称会解析到本函数的作用域

否则,依次考虑更高一层的作用域,直到这个名称会被解析到这个作用域(或者说,在这一级作用域中,存在对这个名称的绑定) ,或者到达global作用域为止。

“存在对某个名称的绑定”,包括赋值语句,也包括之前提到的特殊绑定,以及之后会提到的参数绑定。注意只要存在这样的绑定的语句,哪怕这个语句从未执行,也会导致作用域解析的变化,换句话来说,名称解析到哪个作用域,是函数定义的时候就决定了的:

a = 2

deffunc():ifFalse:

a= 1

return a #UnboundLocalError

然而,具体的解析到值的过程,则是在语句运行时才进行的,这个需要着重注意:

deffunc():

a= 1

deffunc2():returna

a= 2

returnfunc2()

func()#2

初学者经常犯的错误就是这样的:

defmultipliers(n):

funcs=[]for i inrange(0,n):def_func(b):return i *b

funcs.append(_func)returnfuncs

ms= multipliers(10)

ms[2](3) #27, 9 * 3

正确理解了其中的原理之后,这个现象就一点也不难理解了:i在运行时才解析,而运行时,循环已经结束了,所以i是9

每个函数都有自己的global作用域,它是函数定义的Python文件(或者说模块)。它实际上是模块命名空间与__builtins__命名空间两层,其中__builtins__对所有的模块都生效。

参数绑定

对于函数来说,函数的参数的绑定是比较特殊的一个过程,它在调用的时候进行绑定,但是是将传入的参数值,在函数自己的作用域中,绑定到参数名称:

a = 1

deffunc(a):returna

func(2) #2

a #1

它服从一切名称绑定的作用域规则,可以重新绑定,可以del,可以被子作用域解析。

参数可以有默认值,有默认值的情况下,可以理解为实际的参数绑定之前,预先将这些名称绑定到了对应的值,如果调用时指定了新值则重新绑定到新值。

如果既没有默认值、也没有在调用时绑定,就会发生名称未绑定的错误。

小结

Python可以运行表达式,也可以将表达式的值绑定到某个名称

绑定的形式有普通绑定,特殊绑定,参数绑定

绑定与作用域的规则:

默认绑定到当前作用域

解析名称时,会解析到最近一层绑定该名称的作用域

global/nonlocal可以修改这个特性

定义时决定解析到哪个作用域;运行时决定解析的值

前面这么多内容,整理成规则却非常简洁,有没有感受到Python的确是很协调、很纯粹的语言呢?

后记

本文是从面向初学者的一个演示文稿中整理而来,这是前一部分,后一部分讲面向对象。演示文稿当中的一部分更基础的内容,考虑到受众原因没有在这篇文章中提到。

理解Python的规则的另一种方法是了解对象的内部构造,比如code对象内部有哪些成员,cellvars和freevars各代表什么,__closure__属性以及实现,对象的__dict__与属性的关系,等等,有一定编程基础的也推荐这种学习方式。

python语言有哪两个系列_(转)Python学习笔记系列——Python是一种纯粹的语言相关推荐

  1. python 云计算_云计算开发学习笔记:Python的环境搭建

    大家都知道学好Python是进入云计算领域的基础,那么在学习之前我们先来了解下Python环境是如何搭建的.Python可应用于多种平台,包括大家熟悉的Window,Linux 和 Mac OS X. ...

  2. python可以调用c语言编写的底层代码吗_Python基础笔记系列十四:python无缝调用c程序...

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! python语言可以对c程序代码进行调用,以弥补python语言低性能的缺 ...

  3. 《流畅的python》学习笔记之python是什么类型的语言?

    讨论类型时,最好考虑两条不同的坐标线! 强类型和弱类型 如果一门语言很少隐式转换类型,说明它是强类型语言.如果经常这么做,说明它是弱类型语言.其中,java,c++和python是强类型语言,php, ...

  4. python爬取b站视频封面_学习笔记(4)[Python爬虫]:爬取B站搜索界面的所有视频的封面...

    学习笔记(4)[Python爬虫]:爬取B站搜索界面的所有视频的封面 import os import requests import re import json from bs4 import B ...

  5. python编程语言继承_python应用:学习笔记(Python继承)

    学习笔记(Python继承)Python是一种解释型脚本语言,可以应用于以下领域: web 和 Internet开发 科学计算和统计 人工智能 教育 桌面界面开发 后端开发 网络爬虫 有几种叫法(父类 ...

  6. Noah的学习笔记之Python篇:装饰器

    Noah的学习笔记之Python篇: 1.装饰器 2.函数"可变长参数" 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.co ...

  7. z3学习笔记(python 3)

    z3学习笔记(python 3) API API文档1 API文档2 常用API 1.创建约束求解器 solver = Solver() 2.添加约束条件(这一步是z3求解的关键) solver.ad ...

  8. python3.4学习笔记(九) Python GUI桌面应用开发工具选择

    python3.4学习笔记(九) Python GUI桌面应用开发工具选择 Python GUI开发工具选择 - WEB开发者 http://www.admin10000.com/document/9 ...

  9. python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑

    python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件? 当我们点开下载页时, 一 ...

  10. 《python基础教程(第二版)》学习笔记 基础部分(第1章)

    <python基础教程(第二版)>学习笔记 基础部分(第1章) python常用的IDE: Windows: IDLE(gui), Eclipse+PyDev; Python(comman ...

最新文章

  1. 炫酷!用Python制作漂亮的流动桑基图
  2. android安卓应用和OBD的集成场景
  3. 7-166 二分法求多项式单根 (20 分)
  4. display: inline-block;水平居中
  5. python读取matlab数据_两分钟搞定Python读取matlab的.mat数据
  6. java之的读取文件大全
  7. VScode使用记录二:Windows 7下安装GCC、使用VSCode编译代码
  8. 国内做得好的进销存软件有哪些啊?
  9. Java课程设计/大作业合集
  10. React-注册事件
  11. 【转】卖萌的大牛你桑不起啊 ——记CVPR2011一篇极品文章
  12. 水电图纸——管道的预埋和盒子的放置-1
  13. uart口图片_串口(USART)框图的讲解
  14. Jenkins集成GitLab Webhooks自动化构建
  15. beautifulsoup html内容_用python3教你任意Html主内容提取
  16. 用mac的chrome浏览器调试 Android 手机的网页
  17. my ReadHumor work / youmo
  18. iOS中解析json数据
  19. PMBOK(第五版)学习笔记 —— 6 项目时间管理
  20. 飞腾FT-2000/4处理器+复旦微FPGA+国产操作系统解决方案(2)

热门文章

  1. C 与 C++ 40 年的爱恨情仇
  2. verilog or VHDL乒乓球游戏电路设计
  3. 刷机android8.1 错误7,[Android]错误: -source 1.7 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式)...
  4. java后台处理ajax请求_java后台怎么对ajax请求的内容进行xss转义?
  5. php中的round是什么,phpround函数怎么用
  6. filter_var()函数
  7. 双目立体匹配——归一化互相关(NCC)
  8. display:table的几个用法
  9. 在javascript当中发现了一个没有调用者的方法。
  10. Android系统JNI的实现方式