《编写高质量代码 改善python程序的91个建议》读书笔记 之三

31、函数传参,既不是传值也不是传引用

结论:是传对象!
 对不可变类型(数字、字符串及元组),由于对象并不能真正被修改,因此对象值的修改的过程是通过生成一个新的对象然后赋值完成。
 对可变类型(字典、列表、字节数组),对可变对象的修改是在函数外部内部均可见的,调用者和被调用者共享这个对象。

.注:个人的理解,python在这一点上与C++不同,需要开发人员在编程的时候时刻小心,一不小心,对象的值就可能”面目全非“。

 下面的代码:

>>> a = 5	#先开辟一块存储5这个值的内存,将a这个变量(对象)指向这块内存
>>> id(a)
140494650783752
>>> b = a	#将b这个变量指向和a一样的内存空间
>>> id(b)
140494650783752
>>> b = 7
>>> id(b)
140494650783704
>>> id(a)
140494650783752

  其实际的赋值模型见下面的示意图。
在这里插入图片描述

37、按需选择sort()或者sorted()

  • 语法
sorted(iterable[,cmp[,key[,reverse]]])
s.sort([cmp[,key[,reverse]]])

"""
cmp:是用户定义的任何比较函数,函数的参数为两个可比较的元素,函数根据第一个与第二个参数的关系,一次返回-10 或者 +1(第一个参数效益第二个参数返回负数),该参数默认值为None
key:是一个带参数的函数,用来为每个元素提取比较值,默认是None(即直接比较每个元素)
  • sorted()函数可用于任何可迭代对象,而sort一般用于列表;
  • sorted()返回一个排序后的列表,而原列表不变,sort()方法直接修改原有列表,返回值为None;
  • sorted()函数功能更为强大

  - 可以对字典进行排序

>>> phonebook = {'Linda':'7750', 'Bob':'9345', 'Carol':'5834'}
>>> from operator import itemgetter
>>> sorted_pb = sorted(phonebook.iteritems(), key = itemgetter(1))
>>> print (sorted_pb)

[('Carol', '5834'), ('Linda', '7750'), ('Bob', '9345')]

  - 可以对多维list进行排序

>>> from operator import itemgetter
>>> gameresult = [['Bob', 95.00, 'A'], ['Alan', 86.0, 'C'], ['Mandy', 82.5, 'A'], ['Rob', 86, 'E']]
>>> sorted(gameresult, key = itemgetter(2, 1))
[['Mandy', 82.5, 'A'], ['Bob', 95.0, 'A'], ['Alan', 86.0, 'C'], ['Rob', 86, 'E']]

  - 可以对字典中混合list排序

>>> mydict = {'Li':['M', 7], 'Zhang':['E',2], 'Wang':['P',3], 'Du':['C',2], 'Ma':['C',9], 'Zhe':['H',7]}
>>> from operator import itemgetter
>>> sorted(mydict.iteritems(), key = lambda (k,v):itemgetter(1)(v))
[('Zhang', ['E', 2]), ('Du', ['C', 2]), ('Wang', ['P', 3]), ('Li', ['M', 7]), ('Zhe', ['H', 7]), ('Ma', ['C', 9])]

  注:对上面代码的理解:
 1)mydict.iteritems() 将字典mydict的内容以列表的形式返回,返回一个迭代器;
 2)lambda (k,v):itemgetter(1)(v)),定义一个匿名函数,这个函数的输入参数是一个列表(即mydict.iteritems() ),列表的元素对应变量k和v,例如(‘Li’, [‘M’, 7]),其中,k对应key(‘Li’),v对应value([‘M’, 7]),参考元组拆包
 3)lambda函数的函数体,首先“定义”了一个“函数” itemgetter(1),即取得指定对象位置为1的元素,为了便于理解,给这个函数起个名字fun_itemgetter,然后,itemgetter(1)(v) 相当于fun_itemgetter(v),即取得对象v的位置为1的元素作为排序的关键字!这下子明白了吧?!
 多说一句,有时候觉得这种所谓的Pythonic代码,很难理解,可能是我水平有限吧,但过于优美的代码,是不是意味着不好理解呢?

  - 可以对list中混合字典进行排序

>>> gameresult = [{'name':'Bob', 'wins':10, 'losses':3, 'rating':75.00}, {'name':'david', 'wins':3, 'losses':5, 'rating':57.00}, {'name':'Carol', 'wins':4, 'losses':5, 'rating':57.00}, {'name':'Patty', 'wins':9, 'losses':3, 'rating':71.48}]
>>> from operator import itemgetter
>>> sorted(gameresult, key = itemgetter('rating', 'name'))
[{'wins': 4, 'losses': 5, 'name': 'Carol', 'rating': 57.0}, {'wins': 3, 'losses': 5, 'name': 'david', 'rating': 57.0}, {'wins': 9, 'losses': 3, 'name': 'Patty', 'rating': 71.48}, {'wins': 10, 'losses': 3, 'name': 'Bob', 'rating': 75.0}]

*** 学习 from operator import itemgetter ***
以下文字来自:Python operator.itemgetter函数理解

作用:itemgetter 用于获取对象的哪些位置的数据,参数即为代表位置的序号值,

注:这里其他参考资料上’位置’描述的词语是’维度’,我和其他人想法不同,不能称之为维度,准确的描述,应该是位置,因为我发现,itemgetter返回的只是下标,并且只将处理对象看做一维的,详细可以看后面例子的描述
注意:itemgetter 获取的不是值,而是定义了一个函数,通过该函数作用到目标对象上,取出目标对象对应维度的值
例如:

a = [1,2,3] 
b = [[1,2,3],[4,5,6],[7,8,9]] 

注: Python列表、元祖、字典等对象的下标均是从0开始的
这里描述一下我理解的维度,即从线性代数的角度看:

这里,列表a我们可以看做一维数据,上面3个点:a[0] = 1, a[1] = 2, a[2] = 3
列表b则是2维数据,上面是9个点:b[0,0] = 1, b[0,1] = 2, b[0,2] = 3, b[1,0] = 4, …, b[2,2] = 9
理解了上面的描述,就可以更好的理解itemgetter的处理结果了
我们定义取出对象位置1上的数据:

 >>>  get_1 = itemgetter(1)
 >>>  get_1(a) 
 2
 >>>   get_1(b) 
 [4,5,6]

类似:取出对象1,2位置上的数据,并且调整一下顺序:

>>> get_21 = itemgetter(2,1)
>>> get_21(a)
[3,2]
>>> get_21(b)
[[7,8,9],[4,5,6]]

如果要取出b中第2维度上相应位置上的数据,则需要对其中各个子列表进行取数,因为itemgetter的对象是1维对象:

>>>b_21 = []
>>>for temp in b:
        tep = get_21(temp)
        b_21.append(tep)
	# 也可以直接:b_21 = [get_21(temp) for temp in b]
b_21 = [[3,2],[6,5],[9,8]]

*** 学习lambda函数的基本知识 ***
以下文字来自:python – lambda表达式

lambda表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。

lambda所表示的匿名函数的内容应该是很简单的,如果复杂的话,干脆就重新定义一个函数了,使用lambda就有点过于执拗了。

lambda就是用来定义一个匿名函数的,如果还要给他绑定一个名字的话,就会显得有点画蛇添足,通常是直接使用lambda函数。如下所示:

add = lambda x, y : x+y
add(1,2) # 结果为3

那么到底要如何使用lambda表达式呢?
1、应用在函数式编程中

Python提供了很多函数式编程的特性,如:map、reduce、filter、sorted等这些函数都支持函数作为参数,lambda函数就可以应用在函数式编程中。如下:

需求:将列表中的元素按照绝对值大小进行升序排列

list1 = [3,5,-4,-1,0,-2,-6]
sorted(list1, key=lambda x: abs(x))

当然,也可以如下:

list1 = [3,5,-4,-1,0,-2,-6]
def get_abs(x):
    return abs(x)
sorted(list1,key=get_abs)

只不过这种方式的代码看起来不够Pythonic


猜你喜欢

转载自blog.csdn.net/steventian72/article/details/86545525