python核心编程读书笔记(2)

代码对象

概念

可调用的对象是python执行环境里最重要的部分,然而它们只是冰山一角。Python语句、赋值、表达式,甚至还有模块构成了更宏大的场面。这些可执行对象无法像可调用物那样被调用。更确切的说,这些对象只是构成可执行代码块的拼图的很小一部分,而这些代码块被称为代码对象

 

每个可调用物的核心都是代码对象,由语句、赋值、表达式和其他可调用物组成。查看一个模块意味着观察一个较大、包含了模块中所以代码的对象。然后代码可以分成语句、赋值、表达式,以及可调用物。可调用物又可以递归分解到下一层,那儿有自己的代码对象。

 

一般来说,代码对象可以作为函数或者方法调用的一部分来执行,也可用exec语句或内建函数eval()来执行。整体上看,一个python模块的代码对象是构成该模块的全部代码。

 

如果要执行python代码,那么该代码必须要先转换成字节编译的代码(又称字节码)。这才是真正的代码对象。然而,它们不包含任何关于它们执行环境的信息,这便是可调用物存在的原因,它被用来包装一个代码对象并提供额外的信息。

 

函数对象仅是代码对象的包装,方法则是给函数对象的包装,你可以到处看看。当你研究到最底层,你会发现便是一个代码对象。

 

可执行的对象声明和内建函数

Python提供了大量的BIF来支持可调用/可执行对象,    其中包括exec语句。这些函数帮助程序员执行代码对象,也可以用内建函数compile()来生成代码对象。

 

可执行的对象声明和内建函数

内建函数和语句                                描述

callable(obj)                如果obj可调用,返回True,否则返回False

compile(string,file,type)       type类型中创建代码对象;file存放代码(通常设””

eval(obj,globals=globals(),locals=locals()) obj求值,obj为已编译代码对象表达式,或是一个字符串表达式,可以给出全局或者局部的名称空间。

exec obj                   执行obj,单一python语句或者语句集合,也就是说格式是代码对象或者字符串,obj也可以是文件对象(已打开的有效python脚本)

input(prompt=’’)          等同于eval(raw_input(prompt=’’))

 

 

1, callable()

布尔函数,确定一个对象是否可以通过函数操作符”()”来调用。若是返回True,否则False ,(2.2以前返回1和0)

 

>>> callable(dir)     # 内建函数

True

>>>

>>> callable(1)      # 整型

False

>>>

>>> def foo():pass

...

>>> callable(foo)    #自定义函数

True

>>>

>>> callable('bar')   # 字符串

False

>>>

>>> class C(object): pass

...

>>> callable(C)     # 类

True

>>>

>>>

2,             compile()

compile()函数允许程序员在允许时刻迅速生成代码对象,然后就可以用exec语句或者eval()来执行这些对象或者对它们求值。一个很重要的观点: exec和eval()都可以执行字符串格式的python代码。当执行字符串形式的代码时,每次都必须对这些代码进行字节编译处理。compile()函数提供了一次性字节代码预编译,以后每次调用的时候,都不用编译了。

compile()三个参数都是必须的,第一个参数代表了要编译的代码。第二个字符串虽然是必须的,但通常被置为空串。该参数代表了存放代码对象的文件的名字(字符串类型)。compile的通常用法是动态生成字字符串形式的python代码,然后生成一个代码对象(代码显然没有存放在任何文件)。最后一个参数是个字符串,它用来表明代码对象的类型。有三个可能值:

eval       可求值的表达式(和eval()一起使用)

single      单一可执行语句(和exec一起使用)

exec       可执行语句组(和exec一起使用)

 

  a), 可求值表达式

     >>>eval_code = compile('100 + 200','','eval')

>>> eval(eval_code)

300

>>>

  b), 单一可执行语句

>>> single_code = compile('print "hello world!"','' ,'single')

>>>

>>> single_code

<code object <module> at 0x7fd1de13d7b0, file "",line 1>

>>> 

>>> exec single_code

hello world!

>>>

>>> 

 

  c), 可执行语句

>>> exec_code =compile("""

... req = input('Count howmany numbers? ')

... for eachNum inrange(req):

...     print eachNum

... """, '','exec')

>>>

>>> exec exec_code

Count how many numbers? 6

0

1

2

3

4

5

>>>

 

3, eval()

eval()对表达式求值,可以为字符串或内建函数compile()创建的预编译代码对象。这是eval()第一个也是最重要的参数。第二个第三个都是可选的,分别代表了全局和局部空间中的对象。如果给出这两个参数,globals必须是个字典,locals可以是任意的映射对象,比如,一个实现了__getitem__方法的对象。(在2.4之前,local必须是一个字典),如果没有给出,分别默认为globals()和locals()返回的对象,如只传入一个全局字典,则该字典也作为locals传入。

 

>>>eval('932')

932

>>>

>>>int('932')

932

>>> 

两者结果相同,但采用方式不同,内建函数eval()接收引号内的字符串并把它作为表达式进行求值。内建函数int()接收代表整数的字符串转为整数。当我们用纯字符串表达式的时候,两者便不再相同了:

 

>>>eval('100 + 200')

300

>>>int('100 + 200')

Traceback (mostrecent call last):

  File "<stdin>", line 1, in<module>

ValueError:invalid literal for int() with base 10: '100 + 200'

>>> 

 

4, exec

和eval()相似,exec语句执行代码对象或字符串形式的python代码。类似地,用compile()预编译重复代码有助于改善性能,因为在调用时不必经过字节编译处理。Exec语句只接收一个参数,下面是通用用法:

exec obj

 

被执行的对象(obj)可以只是原始的字符串,比如单一语句或是语句组,它们也可以预编译成一个代码对象(分别用’single’和’exec’参数)。

 

>>> exec """

... x = 0

... print 'x is currently:', x

... while x < 5:

...     x += 1

...     print'incrementing x to:', x

... """

x is currently: 0

incrementing x to: 1

incrementing x to: 2

incrementing x to: 3

incrementing x to: 4

incrementing x to: 5

>>>

>>> 

 

   最后,exec还可以接受有效的python文件对象,将上面代码创建为一个xcount.py文件:

   >>>

>>> f = open('xcount.py')

>>> exec f

x is currently: 0

increment x to: 1

increment x to: 2

increment x to: 3

increment x to: 4

increment x to: 5

>>>

   注意:一旦执行完毕,继续对exec调用就会失败,因为exec已从文件中读取了全部数据且停留在文件末尾(EOF),当用相同文件对象调用时已没有可执行代码了。我们用文件对象的tell()方法告诉我们处于文件的何处,然后用os.path.getsize()告诉我们xcount.py脚本大小,你会发现,两个数字完全一样:

   >>> f.tell()

111

>>>

>>> f.close()

>>>

>>> from os.path import getsize

>>>

>>> getsize('xcount.py')

111

>>> 

可以使用seek()再次运行

>>>

>>> f.seek(0)

>>> f.tell()

0

>>>

>>> exec f

x is currently: 0

increment x to: 1

increment x to: 2

increment x to: 3

increment x to: 4

increment x to: 5

>>> f.close()

 

5, input()

内建函数input()是eval()和raw_input()的组合,等价于eval(raw_input).类似于raw_input(),input()有一个可选参数,代表给用户的字符串提示。不给定默认为空串。

 

从功能上看,input()不同于raw_input(),因为raw_input()总是以字符串形式,逐字返回用户的输入。Input()履行相同任务;而且它还把输入作为python表达式进行求值。这意味着input()返回的数据是对输入表达式求值的结果:一个python对象。下面例子会让人更加清楚:当用户输入一个列表时,raw_input()返回一个列表的字符串描绘,而input()返回实际的列表:

>>> aString = raw_input('Enter a list:')

Enter a list:[ 123, 'xyz', 45.67]

>>>

>>> aString

"[ 123, 'xyz', 45.67]"

>>>

>>> type(aString)

<type 'str'>

 

>>> aList = input('Enter a list: ')

Enter a list: [ 123, 'xyz', 45.67 ]

>>> aList

[123, 'xyz', 45.670000000000002]

>>> type(aList)

<type 'list'>

>>>

可见,input()把输入作为python对象来求值并返回表达式的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值