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

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!

感谢

【其他参考】

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

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

https://docs.python.org/devguide/compiler.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值