解读The Python Tutorial(四)

Python最新官方文档目前没有中文版,我用自已的语言来翻义The Python Tutorial,即意义,不是直义。所以会省略一些我认为不重要的内容,但尽量不跳过任何知识点。请对应The Python Tutoria目录来看这一系列文章。

这里写图片描述

4.1. if Statements

elif是else if缩写,if语句与COBOL的EVALUATE相似,其中else相当于other。下例4个分支,程序一定走且只走其中一个分支。优先级依次从上到下,前面三个分支如果不满足就一定走最后一个else分支。

>>> x = int(input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
...     x = 0
...     print('Negative changed to zero')
... elif x == 0:
...     print('Zero')
... elif x == 1:
...     print('Single')
... else:
...     print('More')
...
More
4.2. for Statements
>>> # for语句对数组做只读操作
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
...     print(w, len(w))
...
cat 3
window 6
defenestrate 12

如下,在for循环内部对数组做读写操作,则会导致死循环。即不停地插入defenestrate数据项。

>>> for w in words:  
...     if len(w) > 6:
...         words.insert(0, w)
...

解决此问题的一个办法就是使用”slice切片“ words[:],切片是原数组的一份copy。

 >>> for w in words[:]:  # words[:]是words的一个复制品
...     if len(w) > 6:    
...         words.insert(0, w) #修改的是words,而迭代的是words[:]
...
>>> words                #所以不会死循环,只会插入一个defenestrate
['defenestrate', 'cat', 'window', 'defenestrate']
4.3. The range() Function

for是按顺序遍历的,但如果想跳跃式的遍历。那么用range()函数就比较合适了。

>>> for i in range(5): #默认0开始,默认步进1。直到5(不包含5)
...     print(i)
...
0
1
2
3
4

range(5, 10) #从5开始(而不是从第5个元素开始),直到10(不包含10),默认递进1
5,6,7,8, 9

range(0, 10, 3) #从0开始,直到10(不包含10),递进3
0, 3, 6, 9

range(-10, -100, -30) #从-10开始,直到-100(不包含-100),递进-30
-10, -40, -70

配合len()使用:

>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
...     print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb

range()看起来像是一个数列,但其实它是一个对象,这个对象包含了一些可供迭代的元素项。

>>> list(range(5)) #列出range对象里所有的元素
[0, 1, 2, 3, 4]
>>> range(5)  #返回一个对象
range(0, 5)
>>> 
4.4. break and continue Statements, and else Clauses on Loops

else语句除了可以和if配套使用,还可以和for配合,此时用于循环迭代。当和for配合使用时,for通常有break语句,如果不走break语句则会走else。走break则整个for跳出而结束。

 >>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:  #取余数
...             print(n, 'equals', x, '*', n//x) #//是取商
...             break
...     else:
...         # 整个for(第二个for)走完都没走进break,则会走入else
...         print(n, 'is a prime number')
...
2 is a prime number  #range(2,2)是空数列,直接走else
3 is a prime number  #range(2,3),3%2 !==0,走不进break,走else
4 equals 2 * 2       #range(2,4),4%2 走进break。
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4       #range(2,8),8%2进break,跳出for,后续的8%4没机会走了。
9 equals 3 * 3

continue只是跳出当前这次迭代,继续下一个迭代,并不会跳出整个for循环。

 >>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
4.5. pass Statements

pass什么也不做,有时因为语法要求必须要求你写点什么,但你又什么都不想做。就可以用pass了 例如

 >>> while True:
...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
...
>>> class MyEmptyClass:
...     pass  #啥也不干的类
...
>>> def initlog(*args):
...     pass   # 新程序程序时,暂时没想好怎么写,先用pass空着。
...
4.6. Defining Functions
>>> def fib(n):      # 第一行定义函数
...     """第二行是用三个单双引号起来的函数功能说明文档"""
...     a, b = 0, 1  # 函数正文从第三行开始,而且要缩进
...     while a < n:
...         print(a, end=' ')
...         a, b = b, a+b
...     print()
>>> # 调用函数
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

函数被调起后,会生成一个symbol table用于保存该函数内的这些变量所对应的值。因此变量的值,首先会在函数内symbol table里查找,然后再到上一级函数的symbol table查找,一级级往上找,接着到global symbol table找,最后到built-in names table。(有点像其他语言的变量的作用域)

>>> fib
<function fib at 10042ed0> #symbol table所在地址
>>> f = fib   #fib在稀释器眼中就是用户自定义的函数,可以将fib赋值给其他变量,相当于函数重命名。
>>> f(100)    
0 1 1 2 3 5 8 13 21 34 55 89

没有return关键字的函数默认返回None关键字,解释器通常不会将None打印出来。
return不携带表达式,也返回None。

下例return回一个list

>>> def fib2(n):  # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 0, 1
...     while a < n:
...         result.append(a)    # see below
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # call it
>>> f100                # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
4.7. More on Defining Functions

函数的参数个数是可变的。

4.7.1. Default Argument Values

定义函数时,参数通过=号给默认值,有默认值的参数是可选参数。

def ask_ok(prompt, retries=4, reminder='Please try again!'): 
    while True:
        ok = input(prompt) #input的用法:弹出prompt信息,然后接收用户输入值到ok
        if ok in ('y', 'ye', 'yes'):  #in的用法
            return True
        if ok in ('n', 'no', 'nop', 'nope'):
            return False
        retries = retries - 1
        if retries < 0:
            raise ValueError('invalid user response')
        print(reminder)

定义函数时,如果参数有=号,=后面接的是变量,那么默认值取的是在定义函数的那时候的变量值。事后变量值改变也不会影响到默认参数值。例如:

i = 5
def f(arg=i):
    print(arg)
i = 6
f()会打印5

但有个例外,对于list, dictionary,对象的实例,则:
def f(a, L=[]):
L.append(a)
return L

print(f(1))  [1]
print(f(2)) [1, 2]
print(f(3)) [1, 2, 3]
4.7.2. Keyword Arguments

调用函数时,可以通过=号以键值形式给参数赋值,此时不必按定义函数时参数的顺序赋值。

 def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
       print("-- This parrot wouldn't", action, end=' ')
       print("if you put", voltage, "volts through it.")
       print("-- Lovely plumage, the", type)
       print("-- It's", state, "!")

parrot(action=’VOOOOOM’, voltage=1000000) 这样调用是可以的。

*args 和**kwargs

先来看这个函数,一般习惯test_args_kwargs(1,2,3)调用,结果如下:

def test_args_kwargs(arg1, arg2, arg3):
    print ("arg1:", arg1)
    print ("arg2:", arg2)
    print ("arg3:", arg3)

test_args_kwargs(1,2,3)
arg1: 1
arg2: 2
arg3: 3

但其实有更方便的方法调用:

# first with *args
>>> args = (1, 2, 3)        #将参数设置成一个元组变量或数列变量[1,2,3]     
>>> test_args_kwargs(*args) #将该变量以*号传入函数并调起
arg1: 1
arg2: 2
arg3: 3

# now with **kwargs:
>>> kwargs = {"arg3": 3, "arg1": 1, "arg2":2} #将参数设置成字典 
>>> test_args_kwargs(**kwargs)                #再将参数以**形式传入函数调起
arg1: 1
arg2: 2
arg3: 3

相反,定义函数时也可以用*args 和**kwargs,这时参数个数未定,只有调函数时才知道。
*args用于接收所有位置参数,**kwargs用于接收所有键值参数。
定义同一个函数时*args 必须出现在**kwargs之前。

    def test_var_args(f_arg, *argv):
        print "first normal arg:", f_arg
        for arg in argv:
            print "another arg through *argv :", arg

    test_var_args('yasoob','python','eggs','test')

#结果如下,第一个参数被f_arg捕获,剩下所有的位置参数被*argv获得。

    first normal arg: yasoob
    another arg through *argv : python
    another arg through *argv : eggs
    another arg through *argv : test

又如:

def greet_me(**kwargs):
        if kwargs is not None:
            for key in kwargs:
                print (key,kwargs[key])

>>> greet_me(name="yasoob",hello='LZD')
name yasoob
hello LZD

>>> kwargs={'a':1, 'b':2, 'c':3} # 同样,也可以定义及调用函数同时都用\*args 和\**kwargs
>>> greet_me(**kwargs)
a 1
b 2
c 3
4.7.5. Lambda Expressions

lambda 关键字用于定义一个简单的匿名函数,并return这个函数。
lambda a, b: a+b
冒号前面是lambda 将要返回的函数的参数部分的定义,冒号后面是将要返回的函数的return 部分。即相当于返回了如下一个匿名函数。

def noname(a, b):
    return a+b

又如:

>>> def make_incrementor(n):
...     return lambda x: x + n #返回一个匿名函数,该函数接收一个x参数,并且返回x+n。
...                            #n则是make_incrementor的参数。
>>> f = make_incrementor(42)   #f被赋值为n=42的匿名函数
>>> f(0)                       #返回x+n  x=0,n=42
42
>>> f(1)                       #返回x+n  x=1,n=42
43
4.8. Intermezzo: Coding Style

代码风格:

  1. 使用四个空格缩进。(可以更多)
  2. 每行最多79个字符
  3. 使用空格分隔函数和类,以及函数中的大代码块
  4. 注释单独写一行
  5. 在操作符两边和逗号之后加空格, 括号则不用: a = f(1, 2) + g(3, 4)
  6. 类和函数的命名风格要一致;传统上使用 CamelCase 驼峰风格命名
  7. 使用UTF-8编码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值