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

Python中若干概念和语法糖的廓清:参数、generator与decorator

2016-06-27 19:02 471 查看

Python中若干概念和语法糖的廓清:参数、generator与decorator

Abstract

Python在我们平常的开发中使用很多,以我有限的Python使用经验来看,它未必是一门优雅的语言,但是它有时候确实是一个方便的语言。

我对于Python的使用并不是十分熟练,大量的第三方库让它变的很实用主义,跟Java一样,我不是很喜欢这样的语言,但是相较与Java,我更喜欢用Python一些。虽然,目前的掌握度不怎么样,基本上写Python脚本基本靠查,但是并不满足于扒代码。

现在就参数传递、generator和decorator几个方面,讲一下个中趣味。

Python的参数传递

示例

## for num
a = 1
def inc(b):
b += 1
print b # b+1
print a # 1
inc(a)  # 2
print a # 1

## for list
b = ['hello']
def app(a):
a.append('world')
print a
print b # ['hello']
app(b)  # ['hello', 'world']
print b # ['hello', 'world']


有什么不对吗?是的。整形作为实参,传入函数后,函数内部对形参的修改,并没有带来实参的变化;而list参数却最终引起了传入的实参的变化。这简直很像c/c++语言的按值传递和按指针传递参数。那么Python是不是这种情况呢?

Python的变量是没有类型的,而变量所引用的对象才具有类型。变量就像一个指向内存中对象的指针。但需要区分的是,对象分为:可修改和不可修改。

参数传递的本质就是,对于形参变量的赋值,而赋值的本质就是增加或者减少一个对象的引用计数。

## id 相当于取对象的地址
ii = 123
ll = [1, 2, 3]
print id(ii) ## id of one int ... (1)
print id(ll) ## id of one list... (2)
def print_id_of_parameter(par):
print id(par)
print_id_of_parameter(ii) ## same of (1)
print_id_of_parameter(ll) ## same of (2)


可变对象(list, dict, set,类对象)的更改是对对象内元素,不可变对象的更改是创建一个新的对象。这个可能有一些歧义或者含糊。举个例子。

a = [1, 2, 3]
print id(a) # id of one list
a[0] = 123 # a = [123, 2, 3]
print id(a) # not change
b = (1, 2, 3)
print id(b)
#b[0] = 123 #error, 'tuple' object does not support item assignment
b = (123, 2, 3)
print id(b) #another object of tuple


list对象可以更改其元素,而tuple不能,将b赋一个新的tuple对象,则是一个全新的对象。而整形对象也是不可变的。

如此,联系起来看,则不难理解Python参数传递中那些颇有些让人迷惑的地方了。

generator:生成器

iterator & iterable:迭代器,那么什么是iterator和iterable呢,iterable,可能不准确的说,就是一个序列可以列举出来可迭代的,比如str、list、dict等类型。built-in函数iter(iterable)可以获得一个iterator,iterator是遍历的序列的一个途径,实现为类,通过next方法遍历序列。比如:

class yrange:
def __init__(self, n):
self.i = 0
self.n = n

def __iter__(self):
return self

def next(self):
if self.i < self.n:
i = self.i
self.i += 1
return i
else:
raise StopIteration()
print yrange(5)  #<generator object yrange at 0x......>


generator?是的,generator也是iterator。让一个序列是iterable的,需要实现
__iter__
方法。

iterator->generator:yield关键字

iterator如此有用,是不是必须要实现一个类来实现一个可迭代的序列呢?generator和yield给出了解答。

def yrange(n):
i = 0
while i < n:
yield i
i += 1


如此,可得出,generator实现为一个函数,其运行的机制:

When a generator function is called, it returns a generator object without even beginning execution of the function. When next method is called for the first time, the function starts executing until it reaches yield statement. The yielded value is returned by the next call.

粗糙的说,感觉就是按需生成,一次一个。

‘偷’一个更复杂的例子

def integers():
"""Infinite sequence of integers."""
i = 1
while True:
yield i
i = i + 1

def squares():
for i in integers():
yield i * i

def take(n, seq):
"""Returns first n values from the given sequence."""
seq = iter(seq)
result = []
try:
for i in range(n):
result.append(seq.next())
except StopIteration:
pass
return result

print take(5, squares()) # prints [1, 4, 9, 16, 25]


generator表达式

>>> a = (x*x for x in range(10))
>>> a
<generator object <genexpr> at 0x029C7BE8>
>>> b = [x*x for x in range(10)]
>>> b
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> c = {x*x for x in range(10)}
>>> c
set([0, 1, 4, 81, 64, 9, 16, 49, 25, 36])
>>> iter(b)
<listiterator object at 0x029D1A10>
>>> iter(c)
<setiterator object at 0x029C7878>


很好明白!

itertools 模块

itergtools模块提供一些对iterator的操作,比如
itertools.chain(iter1, iter2)
将两个iterator连接。

这里内容我主要是,拾Iterators & Generators的牙慧,并没有什么新意,而且原文更加清晰好懂。

[未完待续]

Raymond Hettinger, Python’s super() considered super!

感谢

关于函数参数的传递、不可变与可变对象

Iterators & Generators

【其他参考】

http://www.cnblogs.com/P_Chou/p/python-lex-yacc.html

http://everet.org/python-grammar.html

https://docs.python.org/devguide/compiler.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python generator decorator