# 斯坦福编程范式 CS107_25
# 使用 Python 重写 RSG
下面的 grammar 有两个 key,分别映射到一个列表上,其中一个是一个长度为 1 的列表,另一个是长度为 3 的列表。
import sys | |
grammar = {'<struct>':[['This','<object>','is here']],'<object>':[['computer'],['car'],['assiginment']]}; |
假设上述的内容是一个全局变量。我想要定义这个函数。
choice
是一个 python 内置的随机函数,给入一个整数,它会返回介于 0 和那个整数之间的数字;给一个列表,它从列表中等概率地选择任何地元素。 map
用来进行递归。 seed
的作用是生成一个随机数,如果每一次的第一个随机数是相同的总是 0,那么你运行后得到的第二个随机数也是相同的,会得到同一个序列。
def expand(symbol): | |
if symbol.startswith('<'): | |
definitions = grammar[symbol] | |
expansion = choice(definitions) | |
map(expand,expansion) | |
else: | |
sys.out,write(symbol) | |
seed() | |
expand('<start>') |
# 从内存的角度谈一下对象模型
下述例子中,x 和 y 使用的是同一块内存
> x = [1,2,3] | |
> x | |
[1,2,3] | |
> y = x | |
> y | |
[1,2,3] | |
> x.append(4) | |
> x | |
[1,2,3,4] | |
> y | |
[1,2,3,4] |
下面的这个例子,w 没有做任何深度拷贝,没有将 z 列表的所有权转移给那个被 w 拥有的列表,从下面的例子中可以看出来,虽然只是浅拷贝,在 python 的数据生命期中都被预留了。
> z = [10,12,14] | |
> z | |
[10,12,14] | |
> w = [z,z] | |
> w | |
[[10,12,14],[10,12,14]] | |
> z.append(17) | |
> z | |
[10,12,14,17] | |
> w | |
[[10,12,14,17],[10,12,14,17]] |
如果你想要使用复制,那么有两种方法。
有一种模块叫做 copy,可以用来进行复制,生成一个新的内存空间。下面例子中的 z 是进行浅拷贝生成的,它拷贝的深度为 1。
如果想要使用深拷贝,那么可以使用 deep copy
from copy import copy,deepcopy | |
> x = [14,15,21] | |
> x | |
[14,15,21] | |
> y = x | |
> y | |
[14,15,21] | |
> x is y | |
True | |
> z = copy(x) | |
> z | |
[14,15,21] | |
> z = x | |
False | |
> m = [1,2,3] | |
> n = [m,m] | |
> p = deepcopy(n) |
# python 中的对象
python 中的对象和字典差不多而已,在 python 中,没有编译时间元素,不需要预定义类型,直需要将内容添加到字典中。
一个关于类的例子:
class lexicea: | |
def __init__(self,filename = 'words'): |
C++ 中传入对象的地址是在 -1 的参数位置进行传入的,Python 不会那样做,它会很明确地传递有关的容器或对象的地址,包括构造方法,这就是所谓的 self,它不是必须的。self 是是从 objective C 中借来的关键字。因为对象是动态初始化,完全没有编译时元素,它需要这个空的对象。
下面对这个类进行使用:
>>> from lex import lexicea | |
>>> el = lexicea() #构建了类 el | |
>>> lexicea.__dict__ #运行这个会让你看到内部符号其实是以字典的形式进行存放的 |
# 一些易犯的错误
> o = object() | |
> o | |
<---...---> | |
> o.__dict__ | |
{... | |
.... | |
.....} | |
> o.a = 17 | |
> o.b = "hello" | |
> o.c = False | |
> o.__dict__ | |
{'a':17,'b':"hello",'c':False} |
下面的三行代码和 5~7 行的代码是等效的。
o.a = 17 | |
o.b = "hello" | |
o.c = False | |
o.__dict__['a']=17 | |
o.__dict__['b']="helo" | |
o.__dict__['c']=False |
这里所体现出的特点是,支持的对象是可扩展的,收缩的容器。他们必须是以可扩展的方式,那些 C C 和 JAVA 中不需要有的方式,因为 C C JAVA 在任何代码执行之前,已经安排妥当了。Python 是一种完全动态的语言,一切都应该是能扩大和缩小,关于它的一切都应该是动态的,