Python是强类型语言,无法根据上下文自动解析转换成合适的类型。 Python是一种动态语言,在程序运行过程中,同一个变量名在运行的不同阶段可以代表不同形式的值(整型,浮点,列表,元组),变量名只是各种数据及对象的引用。C语言中的变量名是用来存放结果的内存片段。
1、在Python中是通过对象的引用而不是值来赋值给变量的。
2、赋值操作符主要是"=",同时也可使用增量赋值,如 x+=1。但是没有自增、自减操作符。
3、在C语言中,赋值语句可以当作表达式(可以返回值),但是在Python中赋值语句不会返回值,如下面的就是非法的:
以 # 开头的称为注释行。
控制流语句:通过使用or,and,not关键字可以建立任意的条件表达式
None表示空对象。如果一个函数没有显示的返回一个值,None就被返回。None的bool值为false
Python有4种数值类型:整数、长整数、浮点数和复数。所有数值类型都是不可变类型。
python不支持自增自减操作符++,--,++i,其实是+(+i)的意思
运算符与表达式:基本上与其它语言相类似,只是有以下几点不同:
字符串:单引号(‘)和双引号(")的作用相同,只能创建单行字符串。转义符是(\)。
三引号(如:'''或者""")之间的一切都是字符串的内容。
自然字符串:在字符串前加R(或r)指示某些不需要如转义符那样的特别处理的字符串,如:print R“Hello\n World”,将直接输出“Hello\n World”而不会出现换行的情况。
获得子串: s[i:j],返回 s 从i到j(不包括j)之间的子串。若i省略则i=0,若j省略则j=len(s)-1
str() repr() 函数或者向后的引号(`)可以将其他类型的数据转换为字符串。
字符串、Unicode字符串及tuple是不可变的序列。
列表和元组是任意对象的序列,支持的常用操作:
一个元素的元组:a=(12,) #注意一定要个额外的逗号!
对于tuple中的元素,不可以修改,也不可以添加
列表是可变的序列,允许插入,删除,替换元素等操作
字典就是一个关联数组(或称为哈希表),是一个通过关键字索引的对象集合。
使用{}来创建一个字典
字典的key是不能修改的对象(比如数字和tuple)。
range()函数在内存中建立一个列表,当需要一个很大的列表时候,这个占内存且耗时间,为了克服这个缺点,python提供了xrange()。xrange()函数只在需要的时候才临时计算提供值,大大节省了内存。
用户自定义函数有如下属性:
用try和except语句来捕获异常:
如果有IOError异常,就将错误原因放置在对象e中,然后运行except代码块,如果发生其他类型的异常就将控制权转到处理该异常的except的代码块,如果没找到该代码块,程序将终止运行,若没有发生异常,except代
内建函数dir()可以列出一个模块中的所有可访问的内容
可以被import导入的模块:
2.C或C++扩展(已编译的共享库或DLL)
3.包(包含多个模块)
4.内建模块(使用C写的并已链接到python解释器内)
十、引用与副本(引用计数)
python中的一切数据都是对象。
对于可变对象,改变一个引用就等于改变了该对象的所有的引用:
为了避免这种情况,你需要创建一个可变对象的副本,然后对该副本进行操作。
两种创建可变对象的副本:
(1)浅拷贝(shallow copy):创建一个新对象,但它包含的子元素仍然是原来对象子元素的引用:
__del__()在对象销毁时调用。 del x 只是减少对象x的引用计数,并不调用这个函数。
文档字符串DocStrings: 如果一个模块、类、函数体的第一个语句是未命名的字符串,改字符串就自动成为该对象的文档字符串 说白了就是类似于JavaDoc的东西。
文档字符串的惯例是一个多行字符串,它的首行以大写字母开始,句号结尾。第二行是空行,从第三行开始是详细的描述。可以使用__doc__(注意双下划线)调用函数的文档字符串属性(属于函数的名称)。Python把每一样东西都作为对象,包括这个函数。
Python中的help(),它所做的只是抓取函数的__doc__属性,然后整洁地展示给你。
自动化工具也可以以同样的方式从你的程序中提取文档。随Python发行版附带的pydoc命令,与help()类似地使用DocStrings。
id(a)可以查看该对象的标识(当前的实现是该对象在内存中的位置)
# 按照顺序给参数传递值 # 不按照顺序给参数传递值
默认参数就是声明了默认值的参数,因为给参数赋予了默认值,所以在调用函数时,不向该参数传入值也是允许的,后面会有讨论。
通过一个把元组(非关键字参数)或字典(关键字参数)作为参数部分传递给函数,可以在Python中执行一个没有显式定义参数的函数。如下:
当然也可以给出其它形参,包括标准的位置参数(既不是默认参数也不是关键字参数,即按照函数定义时参数的位置来给相应的参数传递值)和关键字参数(函数调用时指定给哪一个参数传递值,其实就是所谓关键字参数了),函数调用的完整语法如下:
如果不确定函数中的参数数目,可以使用可变长度的参数,在Python中,主要包括两种可变长度参数类型,一种是不指定关键字的非关键字可变长参数(元组),而另外一种是指定关键字的关键字可变长参数(字典),不过需要注意如下规则:
两种可变长度的参数都必须位于Formal Arguments(位置参数和默认参数)之后
非关键字可变长参数需要在关键字可变长参数之前
(1)非关键字可变长参数(元组)
(2)关键字可变长参数(字典)
当然,非关键字可变长参数和关键字可变长参数也是可以同时使用的,只需要遵循参数的先后顺序规则即可,如下:
(3)调用带有可变长参数对象函数
直接在参数列表中创建元组和字典
先定义元组和字典对象,再对函数进行调用
不过还有一点需要注意的是,因为还有额外的非关键字参数'3'以及'x'和'y'关键字对,但它们不是'*'和'**'的可变参数中的元素,所以aTuple和aDict参数仅仅是被调函数中最终接收的元组和字典的子集。
关于函数式编程,借用liao Python的解释:
函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
所谓匿名函数,即是没有名字的函数,在Python中,该函数调用完毕后(其实是在创建声明该匿名函数的过程中同时完成调用),就会被Python解释器通过垃圾回收机制进行回收,因为此时它的引用计数已经为0了。
一个完整的lambda“语句”代表了一个表达式,这个表达式的定义体必须和声明放在同一行,同时,参数是可选的,如果使用参数的话,通常参数也是表达式的一部分。
lambda表达式返回可调用的函数对象:
用合适的表达式调用一个lambda生成一个可以像其他函数一样使用的函数对象。它们可以被传给其他函数,用额外的引用别名化,作为容器对象以及作为可调用的对象被调用(如果需要的话,可以带参数)。当被调用的时候,如果给定相同的参数的话,这些对象会生成一个和相同表达式等价的结果。
lambda表达式可以和单行的函数等价
不过不同的是,单行的函数在定义后还是存在的,因为有引用,但是lambda表达式生成的函数对象就会马上被回收,因为没有被引用。
这些函数提供了Python函数式编程的特性,而lambda函数可以很好地和使用了这些函数的应用程序结合起来,因为它们都带了一个可执行的函数对象,lambda表达式提供了迅速创建这些函数的机制。
用可选的参数来调用func,nkw为非关键字参数,kw为关键字参数;返回值是函数调用的返回值 (该函数已经不建议使用) |
调用一个布尔函数func来迭代遍历每个seq中的元素;返回一个使func返回值为true的元素的序列 (可以通过列表的综合使用来替代) |
将函数func作用于给定序列(s)的每个元素,并用一个列表来提供返回值;如果func为None,func表现为一个身份函数,返回一个含有每个序列中元素集合的n个元组的列表 |
将二元函数作用二seq序列的元素,每次携带一对(先前的结果以及下一个序列元素),连续地将现有的结果和下一个值作用在获得的随后的结果上,最后减少序列为一个单一的返回值;如果初始值init给定,第一个比较会是init和第一个序列元素而不是序列的头两个元素 |
第一次重构:使用lambda表达式
第二次重构:通过列表的综合使用替换filter()
第三次重构:进一步简化代码
将函数func并行(如果存在多个序列的话)作用(迭代)于每一个序列中的每一个元素,将所得结果保存在一个列表中,如下:
reduce()函数通过取出序列的头两个元素,将它们传入二元函数来获得一个单一的值来实现。然后又用这个值和序列的下一个元素来获得又一个值,之后继续直到整个序列的内容都遍历完毕以及最后的值被算出来为止。
所谓偏函数,其实就是把一个函数的某个参数固定下来,虽然可以通过函数的默认参数来实现这个功能,但是使用偏函数会方便很多。
但是如果每次都需要相加或相乘同一个数,这样的话就需要每次给add和mul传递两个参数,会比较麻烦。使用functools模块中的partial函数,就可以把一个函数中的某个参数固定下来,这样在下次调用这个函数时,就可以省略一个参数了,如下:
那是因为如果不指定关键字参数,则固定的参数是放到原来函数最左边的,显然如果int()函数的第一个参数为一个数字时就肯定会有异常。
(1)全局变量与局部变量
定义在函数内部的局部变量形成局部作用域,而定义在模块中的全局变量形成全局作用域,但不管局部变量还是全局变量,都存放在它们对应的名称空间中(局部名称空间和全局名称空间)。
如果在一个内部函数里,对在外部作用域(但不是在全局作用域 )的变量进行引用,那么内部函数就被认为是闭包(closure),定义在外部函数内的但由内部函数引用或者使用的变量就被称为自由变量。
闭包是一个函数,只是它们能携带一些额外的作用域,它们所引用的上层函数的变量,既不属于全局名称空间,也不属于这个内部函数的局部名称空间,而是属于其它名称空间,因此说闭包带着“流浪”的作用域。
# 虽然f3也有使用y,但对于f2()来说,y是局部变量,不是闭包变量 # 至于f3()使用的w和z,则分别为全局变量和f3的局部变量
如果f2()使用了任何的定义在f1()作用域的变量,比如说,非全局的和非f2()的局部域的,那么它们便是自由变量,将会被f2.func_closure追踪到。
另外可以看到对自由变量的引用是存放在一个称为"cell"的单元对象里,单元是作用域结束后使自由变量的引用存活的一种基础方法:
假设函数f3()已经被传入到其他一些函数,这样便可在稍后,甚至是f2()完成之后调用它。你不想让f2()的栈出现,因为即使我们仅仅在乎f3()使用的自由变量,栈也会让所有的f2()的变量保持存活。单元维持信自由变量以便f2()的剩余部分能被释放掉。
在f3()、f2()或f1()中都是找不到变量w的,因为这是个全局变量;在f3()或者f2()中,找不到变量x,因为它是来自f1()的闭包变量;同样,y是一个来自f2()的闭包变量;最后,z是f3()的局部变量。
高级闭包和装饰器的例子
来看一个综合运用了闭包和装饰器的例子,主要是用来选择是先写入日志再打印还是先打印再写入日志的功能,如下:
Python的lambda匿名函数遵循和标准函数一样的作用域规则,一个lambda表达式定义了新的作用域,因为它的局部变量也存放在它的局部名称空间中,在函数内部使用lambda表达式时,可以把其作为一个嵌套函数来看待,只是这个函数没有名字而已。
(5)变量作用域和名称空间
变量作用域指的是变量可以使用的范围,而名称空间则是一种数据结构,在这个范围内,这个作用域的变量应该是保存在这个名称空间中。
locals()存放的是局部变量的名称空间
test2()可以使用test1()中的变量,那是闭包的概念
协同程序是可以运行的独立函数调用,可以暂停或者挂起,并从程序离开的地方继续或者重新开始。在调用者和(被调用的)协同程序也有通信。举例来说,当协同程序暂停的时候,我们能从其中获得一个中间的返回值,当调用回到程序中时,能够传入额外或者改变了的参数,但仍能够从我们上次离开的地方继续,并且所有状态完整。挂起返回出中间值并多次继续的协同程序被称为生成器,那就是Python的生成器真正在做的事。
从语法上讲,生成器是一个带yield语句的函数。一个函数或者子程序只返回一次,但一个生成器能暂停执行并返回一个中间的结果——那就是yield语句的功能,返回一个值给调用者并暂停执行(即yield产生一个结果并返回给调用者)。当生成器的next()方法被调用的时候,它会准确地从离开的地方继续。
(1)简单的生成器特性
(2)加强的生成器特性
每一次next()的执行,都会yield出一个值并返回,同时保持原来函数的执行状态,当执行下一次next()时,继续上一次yield语句的下一条语句,然后直到遇到下一个yield语句并返回一个值,以此类推。
python3中查看类的内建属性和方法:
子类没有实现__init__
方法时,默认自动调用父类的。 如定义__init__
方法时,需自己手动调用父类的 __init__
方法。
创建实例后,赋值时使用,在__new__ 后
|
|
实例字符串表示(可读性) | print(类实例),如没实现则使用repr结果 |
实例字符串表示(准确性) | |
程序执行else里面的代码时,即return self.test,因为return需要把self.test的值返回,那么首先要获取self.test的值(test方法名所对应的函数体的地址),因为self此时就是t这个对象,所以self.test就是t.test,此时要获取t这个对象的test属性,那么就会跳转到__getattribute__方法去执行,即此时产生了递归调用,由于这个递归过程中没有判断什么时候推出,所以这个程序会永无休止的运行下去,又因为每次调用函数,就需要保存一些数据,那么随着调用的次数越来越多,最终内存吃光,所以程序崩溃。
启动python解释器,输入dir(__builtins__),,可以看到很多python解释器启动后默认加载的属性和函数,这些函数称之为内建函数(Build-in Function),这些函数因为在编程时使用较多,cpython解释器用c语言实现了这些函数,启动解释器时默认加载。
这些函数数量众多,不宜记忆,开发时不是都用到的,待用到时再使用 help(function) 查看如何使用,或结合百度查询即可,在这里介绍些常用的内建函数。
python2中range返回列表,python3中range返回一个迭代器。如果想得到列表,可通过list函数:
map函数会根据提供的函数,对指定序列做映射。
参数序列中的每一个元素分别调用function函数,返回包含每次function函数返回值的list(python3中返回迭代器)。
filter函数会对指定序列执行过滤操作。
filter函数会对序列参数sequence中的每个元素调用function函数,最后返回的结果包含调用结果为True的元素。返回值的类型和参数sequence的类型相同(python3中返回迭代器)。
reduce函数会对参数序列中元素进行累积。
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。