《Python基础教程》读书笔记05-基础知识进阶

import

import somemodule
from somemodule import somefunction
from somemodule import somefunction, anotherfunction, yetantherfunction
from somemodule import * # 如果确定从给定模块导入所有功能时使用。
import math as foobar # 使用别名
import math import sqrt as foobar # 为函数提供别名

range() 函数和 xrange() 函数

Python3 取消了 xrange() 函数,并且和 range() 函数合并为 range()

Python2.7 环境

>>> range(8)
[0, 1, 2, 3, 4, 5, 6, 7]
>>> a = range(8)
>>> print(type(a))
<type 'list'>
>>> b = xrange(8)
>>> type(b)
<type 'xrange'>
>>> [ x for x in b]
[0, 1, 2, 3, 4, 5, 6, 7]

Python3 环境

>>> a = range(8)
>>> type(a)
<class 'range'>
>>> [ x for x in a]
[0, 1, 2, 3, 4, 5, 6, 7]

>>> b = xrange(8)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined

赋值魔法

赋值语句的一些技巧

序列解包

# 多个赋值操作同时进行
>>> x, y, z = 1, 2, 3
>>> print (x, y, z)
1 2 3
# 交换两个或多个变量
>>> x, y = y, x
>>> print(x, y, z)
2 1 3

事实上,这里所做的事情叫做序列解包,或递归解包————将多个值的序列解开,然后放到变量中。更形象一点儿的表示就是:

>>> value = 1, 2, 3
>>> value
(1, 2, 3)
>>> x, y, z = value
>>> x
1

当函数返回元组(或序列字典等)时,这个特性十分有用。

>>> x = {'name': 'zhang', 'age': 18}
>>> key, value = x.popitem()
>>> key
'age'
>>> value
18

所解包的序列中元素数量必须和 '=' 号左边的变量数量完全一致

Python3 中有另一个解包的特性,可以使用星号运算符(可变参数)

>>> a, *b = [1,2,3,4]
>>> a
1
>>> b
[2, 3, 4]
>>> *a, b = [1,2,3,4]
>>> a
[1, 2, 3]
>>> b
4

链式赋值

将一个值赋给多个变量

x = y = somefunction()
# 和下面的语句等同
x = somefunction()
x = y
# 注意上面的语句和下面的不一定等价
x = somefunction()
y = somefunction()

条件,bool

False None 0 "" () [] {}这些值作为布尔表达式的时候,都会被认为 False,其他的一切都被认为 True。

bool函数

>>> bool(0)
False

条件语句:if elif else

布尔运算符:and or not

布尔运算符的短路逻辑

表达式 x and y 中,如果 x 为假,表达式返回 x 的值,否则返回 y 的值。

>>> x = {}
>>> y = 1
>>> z = x and y # 返回 x 的值
>>> z
{}
>>> x = 2
>>> z = x and y # 返回 y 的值
>>> z
1

在表达式 x or y 中,x 为真返回 x 的值,否则返回 y 的值

>>> x = ''
>>> z = x or 'unknown' # 如果为空,返回默认值
>>> z
'unknown'

三元运算符

a if b else c:如果 b 为真,返回 a,否则返回 c。

比较运算符

支持 1<= x <= 10,这种格式

相等运算符'=='

>>> x = {'name': 'zhang'}
>>> y = {'name': 'zhang'}
>>> x==y
True

is: 同一性运算符

>>> x==y
True
>>> z = x
>>> z is x
True
>>> x is y
False

== 运算符判断两对象是否相等,is 判定两者是否等同(同一对象),避免将 is 运算符用于比较类似数值和字符串这类不可变值。

in: 成员资格运算符

>>> 'name' in x.keys()
True
>>> 'name' not in x.keys()
False

断言

确保程序中的某个条件一定为真。

>>> age = -1
>>> assert 0 < age < 100, 'The age must be realistic' # 可以添加字符串解释断言
Traceback (most recent call last):
  File "<pyshell#58>", line 1, in <module>
    assert 0 < age < 100, 'The age must be realistic'
AssertionError: The age must be realistic

迭代

并行迭代

x = ['a', 'b', 'c']
y = [1, 2, 3]
for i in range(len(x)):
    print (x[i], ':', y[i])

# a : 1
# b : 2
# c : 3

使用内建函数 zip,进行并行迭代,可以将两个序列“压缩”在一起,然后返回一个元组的列表。

zip(x, y)
# [('a', 1), ('b', 2), ('c', 3)]  # Python2
# <zip object at 0x033B8378> # Python3

for i, j in zip(x, y):
    print (i, ':', j)

# a : 1
# b : 2
# c : 3

zip 函数可以处理不等长序列,当最短的序列用完时就会停止。

>>> zip(range(5), range(1000000))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] # Python2

按索引迭代

在一个字符串列表中替换所有包含 'yy' 的子字符串

strings = ['xxx', 'yyy', 'zzz']
index = 0
for string in strings:
    if 'yy' in string:
        strings[index] = 'aaa'
    index += 1

>>> strings
['xxx', 'aaa', 'zzz']

使用内建函数 enumerate

for index, string in enumerate(strings):
    if 'zz' in string:
        strings[index] = 'bbb'

>>> strings
['xxx', 'aaa', 'bbb']

这个函数可以在提供索引的地方迭代索引——值对。

翻转和排序迭代

reversed 和 sorted,同列表的 reverse 和 sort 的方法相似,在列表一节中有介绍。

作用于任何序列或可迭代对象,不修改原对象,返回修改后的版本(reversed 返回一个迭代对象)。

>>> sorted([4, 2, 6, 8, 3])
[2, 3, 4, 6, 8]
>>> sorted('Hello, World')
[' ', ',', 'H', 'W', 'd', 'e', 'l', 'l', 'l', 'o', 'o', 'r']
>>> reversed('Hello, World') # 返回迭代对象,不能直接使用索引、分片、list 方法等,使用 list 转换就可以使用了
<reversed object at 0x033B3B30>
>>> list(reversed('Hello, World'))
['d', 'l', 'r', 'o', 'W', ' ', ',', 'o', 'l', 'l', 'e', 'H']
>>> ''.join(reversed('Hello, World')) # 可以在 join 方法中使用
'dlroW ,olleH'

列表推导式

>>> [x * x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> [x * x for x in range(10) if x % 3 == 0]
[0, 9, 36, 81]

>>> [(x, y) for x in range(3) for y in range(3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

>>> boys = ['a2', 'b2', 'c2']
>>> girls = ['a1', 'b1', 'c1']
>>> [b + '+' + g for b in boys for g in girls if b[0] == g[0]]
['a2+a1', 'b2+b1', 'c2+c1']

男孩/女孩名字对,有效率更高的方法

letterGirls = {}
for girl in girls:
    letterGirls.setdefault(girl[0], []).append(girl)

[b + '+' + g for b in boys for g in letterGirls[b[0]]]

# ['a2+a1', 'b2+b1', 'c2+c1']

创建了一个字典,以首字母为键,女孩名为值。字典创建后,列表推导式循环整个男孩集合。这样就不用尝试所有的男孩女孩组合了。

pass

在 Python 中空代码块是非法的。

if(True):
    pass
else:
    print ('False')

if(True):

else:
    print ('False')
# SyntaxError: expected an indented block

del

>>> x = [11,22,33]
>>> y = x
>>> del x
>>> y
[11, 22, 33]
>>> x
Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    x
NameError: name 'x' is not defined

del 不会删除列表本身,只是删除指向,Python 解释器会负责内存的回收。

exec 和 eval

不常用。

exec

在使用 exec() 之前,你可能需要问下自己是否有其他更好的替代方案。大多数情况下当你要考虑使用 exec() 的时候, 还有另外更好的解决方案,比如装饰器、闭包、元类,或其他一些元编程特性。

执行一个字符串语句

>>> exec('print ("dd")') # Python3 exec,print都需要加()
dd

可以给 exec 语句 提供命名空间,从而使字符串代码不会干扰到其他代码。

>>> from math import sqrt
>>> exec ("sqrt = 1")
>>> sqrt(4)
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    sqrt(4)
TypeError: 'int' object is not callable

因为字符串语句,很可能是从其他地方获得的。

Python2

为了安全起见,可以增加一个字典,起到命名空间的作用

>>> from math import sqrt
>>> scope = {}
>>> exec 'sqrt = 1' in scope
>>> sqrt(4)
2.0
>>> scope['sqrt']
1

Python3

见:9.23 在局部变量域中执行代码

def test():
     a = 13
     exec('b = a + 1')
     print(b)

>>> test()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 4, in test
NameError: global name 'b' is not defined
>>>
# 大部分情况下,这种方式是使用 exec() 的最佳实践。 你只需要保证全局和局部字典在后面代码访问时已经被初始化。
def test4():
     a = 13
     loc = { 'a' : a }
     glb = { }
     exec('b = a + 1', glb, loc)
     b = loc['b']
     print(b)

>>> test4()
14

eval

eval会计算 Python 表达式(以字符串形式书写),实际使用需要防止安全问题。

语法:

eval(expression[, globals[, locals]])

参数

  • expression -- 表达式。
  • globals -- 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
  • locals -- 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。
>>> eval(raw_input('input: ')) # 等同于input(),Python3中,raw_input被重命名为input
input: 6 + 5*3
21

>>> eval('1+2')
3

为eval提供命名空间

>>> scope = {}
>>> scope['x'] = 2
>>> scope['y'] = 3
>>> eval('x * y', scope)
6

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com

文章标题:《Python基础教程》读书笔记05-基础知识进阶

文章字数:2.5k

本文作者:Bin

发布时间:2017-01-01, 17:17:55

最后更新:2019-08-06, 00:07:35

原始链接:http://coolview.github.io/2017/01/01/Python%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/%E3%80%8APython%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B005-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E8%BF%9B%E9%98%B6/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录