Python开发基础总结(二)函数+闭包+字典+列表
目录
一、函数的使用:
1、函数的作用域:函数中定义一个变量,如果和全局变量重名,则全局变量名称就会被覆盖,也就是,这里对这个变量的更改,不会更改全局变量。但是,如果直接使用的话,是会使用全局变量的。同时,如果想要修改全局变量,需要制定是全局变量:global a
2、xrange用法和range一样,不过更为高效,因为他不会在内存中创建列表。所以,它只能用于循环。
3、如果函数没有return语句,则他的返回值为None。
4、关于函数的入参判断:如果如此为空,可能会发生异常。当异常发生后,可能会出现一种情况,一个事情做到了一半,就没有在进行下去,可能会造成内存泄露。这个问题如何解决?按照C的方式,每个入参都做判断是可以解决的,但是这样太麻烦了。而且看很多开源代码页没有这样来做。是不是有更好的方法?换一种思路,在调用之前确保不为空。在看看开源的代码是怎么做的。特别是openstack。
5、可变入参:*args, **kwargs表示可变入参。
-
def funtest(a, b, c):
-
-
print(a, b, c)
-
-
def fun2(*args, **kwargs):
-
-
funtest(*args, **kwargs)
-
-
fun2(1,2,3)
也可以这样定义:
fun2(a, *args, **kwargs)
如何从可变参数中解析出参数的值?
在fun2中添加打印:可以发现,其实args是一个元组,kwargs是一个字典。
分析:调用fun2(1,2,3),会把a赋值给a,2赋值给元组args,{‘c’=3}赋值给kwargs.
args和kwargs的顺序不可颠倒。
args和kwargs可能同时都有值。这样,要获取指定的入参,首先根据看args中有没有,然后根据字符串看kwargs中是否存在。
如何建一个元组或者字典通过参数传递给一个函数?
-
def funtest(a, b, c):
-
-
print(a, b, c)
-
-
d = {'a':1, 'b':2,'c':3}
-
-
l = (1,2,3)
-
-
funtest(*l)
-
-
funtest(**d)
*和**在Python中可以实现这个功能。这样会很灵活的。
*和**也可以单独出现。但是,如果同时出现,*必须在**之前。
6、默认参数或者可选参数,参数顺序:调用时,可以指定默认参数中填充那个。
-
def funtest(a, b=1, c=2):
-
-
print(a, b, c)
-
-
funtest(1, c=5, b=6)
其实,即便定义为:def funtest(a, b, c),也可以通过funtest(1, c=5, b=6)的形式调用。
7、参数组:*args, **kwargs就是参数组,通过元组和字典将产生携带进来。这个特性有助于更为动态的代码生成。
8、可变长度参数:
9、函数的参数中如果有一个是元组,可以这样:
-
def fun(a, (b, c)):
-
-
print(a, b, c)
-
-
fun(1, (1,2))
10、关于回调,可以使用闭包,生成器,以及对象的__call__属性。都可以封装状态。
二、闭包的使用:
1、将组成函数的语句和语句的执行环境打包在一起形成的对象,成为闭包。
2、2.7之前的闭包不支持关键字nonlocal。3.0之后才支持。所以2.7前的闭包不可以使用nonlocal。
3、这样他就不可以对执行环境中的变量进行更改。
三、字典的使用:
1、字典的删除:直接使用del dict[k]可能会引发异常;首先判断k是否存在则效率有些低;使用异常使程序结构看起来不好。一个好的方法是pop(k, default v)。这个删除一个k项,并且返回。如果不存在返回默认的v。如果不加默认值,则会引发异常。
2、直接使用字典下标获取字典的值可能会引发一场。使用get方法则不会,如果不存在会返回none。另外,还可以设置不存在的默认值。
3、通过字典格式化字符串:print “value is %(key)s” % kvdict
4、items方法返回一个列表,列表中的元素是一个元组,第一个是key,第二个是value。比较好用的方法。
5、iteritems:返回的是一个迭代器。如果想要迭代这个字典,iteritems会比items更高效一点。
6、iterkeys则返回的是key的迭代器。keys返回的是key的list。
7、values返回值的列表,itervalues返回的是vlaue的迭代器
8、popitem会随机弹出(同时删除)一个项,则对于想要处理所有的元素,并且删除所有的元素是有帮助的。但是,如果没用元素的话,会抛出异常。
9、viewitems,viewkeys,viewvalues:这三个函数返回的是一个view对象。这个类似于视图。分别表示(key, value)pair的列表,key的列表,value的列表。一个优点是,如果字典发生变化,view会同步发生变化。在迭代过程中,字典不允许改变,否则会报异常。
10、字典的键值比较规则:如果是内置类型(int,str,tuple),则是以他们的值作为键值;如果是自定义对象,则是以对象的地址作为键值。——这一点没有完全证实。——最新的发现:对象的比较,内置类型,是因为他们都重写了默认的object的__eq__等方法,所以可以比较内容。自定义对象,没有重写,所以,他们的比较可能会不一样。object默认的比较是什么?目前还不明确,后面再补充吧。可能就是地址(或者对象的唯一标识),而不是对象的内容。涉及到字典,它不是使用的单纯的比较,而是使用的__hash__,它返回的是一个hash值,字典就是根据这个hash只来散布对象的。
四、列表的使用:
1、列表的删除:不可以在遍历的过程中删除链表,这样会得到不可预知的后果。可以使用列表的过滤,来获得新的列表。
2、列表的过滤:
def filterFun(node):#这个函数做了两个事情哎。
-
node.cycleCount = node.cycleCount - 1
-
-
return node.cycleCount < 0
-
-
timeoutList = filter(filterFun, timerList)
对timerList中的每个节点执行函数filterFun,根据filterFun返回的结果,为真的项组成一个新的列表。
3、map: kvlist = map(lambda x:x.strip(), kvlist)。同时,map可以接受多个列表,这个时候,函数也会接受多个参数,分别表示列表的每一个元素:
kvlist = map(lambda x,y:x+y, [1,2,3], [4,5,6])
如果函数为None,则相当于函数zip:
zip([1,2,3], [4,5,6])
[(1,4),(2,5),(3,6)]
4、生成器表达式:l = [node for node in xrange(5) if node - 3 < 0]:这个的这个方法一定程度上可以替代过滤器和map。
生成器表达式定义:
[expr for iter_var in iterable if cond_expr]
l = [2 for x in xrange(5)]#结果是生成一个含有5个2的列表
- print(reduce(lambda x,y: x*y, [2 for x in xrange(38)]))
上面的这个语句是计算2的38次方的值。它用到的是二元函数reduce。它第一次调用是将第一个和第二个元素做入参,后面用他们的结果做x,新的元素做y,最后返回值。
另外,在获取一个38个2的列表也可以使用:[2] * 38。这可能更可读一点。
5、enumerate:对列表处理,返回的是列表的索引以及节点。
for index, node in enumerate(timerList):
if timerId == node.timerId and timerEvent == node.timerEvent:
del timerList[index]
6、列表的分片:[1,2,3,4],l[1:-1]表示从索引从1到倒数第一个,不包含倒数第一个。如果要从某位置到最后,则应该:[1:]
7、l[i:j:k]:表示切片,从i到j,步长为k。
8、l[i:j]:表示从i到j,不包括索引j。
文章来源: zhulin1028.blog.csdn.net,作者:zhulin1028,版权归原作者所有,如需转载,请联系作者。
原文链接:zhulin1028.blog.csdn.net/article/details/121254616
- 点赞
- 收藏
- 关注作者
评论(0)