Python学习【二】流程控制

一、if 语句

与 C 不同,Python 的 if 没有大括号 { } 代表作用域, 而是通过相同的缩进来表示在同一块作用域,而且判断语句最后要加 :

举个栗子:

x = int(input("Please enter an integer: "))
if x < 0:
    x = 0
    print('Negative changed to zreo')
elif x == 0:
    print("Zero")
elif x == 1:
    print('Single')
else:
    print('zjj')

可能会有零到多个 elif 部分,else 是可选的。关键字 ‘elif’ 是 ’else if’ 的缩写,这个可以有效地避免过深的缩进。if … elif … elif … 序列用于替代其它语言中的 switch 或 case 语句。

二、for 语句

Python 中的 for 语句和 C 或 Pascal 中的略有不同。通常的循环可能会依据一个等差数值步进过程(如 Pascal),或由用户来定义迭代步骤和中止条件(如 C ),Python 的 for 语句依据任意序列(链表或字符串)中的子项,按它们在序列中的顺序来进行迭代。

即 C 中的迭代步长和中止条件是可自定义的,而Python的迭代是按照子项按顺序迭代的。(迭代过程更加麻瓜...)

例如(没有暗指):

Str = ['You', 'look', 'so', 'beautiful']
for w in Str:
    print(w, len(w))

You 3
look 4
so 2
beautiful 9

在迭代过程中修改迭代序列不安全(只有在使用链表这样的可变序列时才会有这样的情况)。如果你想要修改你迭代的序列(例如,复制选择项),你可以迭代它的复本。使用切割标识就可以很方便的做到这一点:

因为迭代过程是根据序列中的子项进行按顺序迭代的,在字符串中,因为字符串是不可修改的数据类型所以无需担心迭代出错的问题,而列表是可修改的数据类型,假设迭代过程中我们修改了其中的值会影响到迭代过程。为了保证迭代的准确性,可以复制一份数据来进行迭代而对原数据进行迭代修改。

Str = ['You', 'look', 'so', 'beautiful']
for w in Str[:]:
    if(len(w) > 6):
        Str.insert(len(Str), w)
Str
['You', 'look', 'so', 'beautiful', 'beautiful']

三、range()函数

如果你需要一个数值序列,内置函数 range() 会很方便,它生成一个等差级数链表:

tt = range(5)
print(tt)
for i in range(5):
    print('r:',i)
    print('tt[',i, ']:',tt[i])

range(0, 5)
r: 0
tt[ 0 ]: 0
r: 1
tt[ 1 ]: 1
r: 2
tt[ 2 ]: 2
r: 3
tt[ 3 ]: 3
r: 4
tt[ 4 ]: 4

range(x, y, z)生成了一个包含 [x, y) 值的链表,, z为增长的步长(可以为负数)。需要迭代链表索引的话,如下所示结合使 用 range() 和 len()

tt = range(3, -10, -3)
print(tt)
for i in range(len(tt)):
    print('r:',i)
    print('tt[',i, ']:',tt[i])

range(3, -10, -3)
r: 0
tt[ 0 ]: 3
r: 1
tt[ 1 ]: 0
r: 2
tt[ 2 ]: -3
r: 3
tt[ 3 ]: -6
r: 4
tt[ 4 ]: -9

在不同方面 range() 函数返回的对象表现为它是一个列表,但事实上它并不是。当你迭代它时,它是一个能够像期望的序列返回连续项的对象;但为了节省空间,它并不真正构造列表。

我们称此类对象是 可迭代的,即适合作为那些期望从某些东西中获得连续项直到结束的函数或结构的一个目标(参数)。我们已经见过的 for 语句就是这样一个迭代器。list() 函数是另外一个( 迭代器 ),它从可迭代(对象)中创建列表:

四、break、continue、循环中的 else 语句

break 与 continue 与 C 中的类似

而循环中的 else 语句可以简洁地解决循环中的判断分支问题,假设需要循环来判断一个条件的正或者假(例如朴素的判断素数),在C中需要一个变量来标识是否可以再分解,而 python 可以通过循环中的 else 语句来进行判断分支。

for n in range(2, 10):
    for x in range(2, n):
        if(n%2 == 0):
            print(n, '=', x, '*', n//x)
            break;
    else:
        print(n, 'is a prime number')

2 is a prime number
3 is a prime number
4 = 2 * 2
5 is a prime number
6 = 2 * 3
7 is a prime number
8 = 2 * 4
9 is a prime number

五、pass语句

pass 语句什么也不做。它用于那些语法上必须要有什么语句,但程序什么也不做的场合,例如:

while True:
    pass  # Busy-wait for keyboard interrupt (Ctrl+C)
    print('ashdfi')
    break

六、函数

斐波那契栗子:

def fib(n):
    a, b = 0, 1;
    while a < n:
        print(a, end = ' ');
        a, b = b, a+b;
    print();
fib(2019);

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 

关键字 def 引入了一个函数 定义。在其后必须跟有函数名和包括形式参数的圆括号。函数体语句从下一行开始,必须是缩进的。

按照常识,我们发现上面定义的函数并没有 return,但这并不代表它没有返回值。没有return语句的函数会返回一个 None 值,可以通过print()来观察它。

关于函数的局部变量,函数调用时会为局部变量生成一个新的符号表,所有函数中的变量赋值都是将值存储在局部符号表。变量引用首先在局部符号表中查找,然后是包含函数的局部符号表,然后是全局符号表,最后是内置名字表。因此,全局变量可以被引用,但不能在函数中直接赋值(除非用global语句命名)。

当一个函数被另一个函数调用时,一个新的局部符号表在调用过程中被创建。

Python中的通用重命名机制:新定义的函数名 = 原函数名

f = fib
f

<function __main__.fib(n)>

6.1 默认参数值

类似于C++,但是不同的是默认值只在函数定义时被赋值一次,回到上面的函数调用时的局部变量,其实可以理解为定义是这个默认值就在那里了,对于不可更改的数据类型没有大碍,但是对于可变的数据类型,这样会导致多次调用的结果被叠加。

def f(a, L=[]):
    L.append(a);
    return L;

print(f(1));
print(f(2));
print(f(3));

[1]
[1, 2]
[1, 2, 3]

如果不希望出现这样的结果,最常见的做法是:

def f(a, L=None):
    if(L is None):
        L = [];
    L.append(a);
    return L;

print(f(1));
print(f(2));
print(f(3));

然后弱鸡本人想到了另一个栗子:

def f(a, L=[]):
    L = L + [a];
    return L;

print(f(1));
print(f(2));
print(f(3));

这个的结果也是不重叠的,原因不才认为是 通过 = 号赋值其实是新建了一个变量,也就是原本赋默认值的那个局部变量并没有改变,而是新产生了一个变量,所以也就不会重叠。Python的赋值和存储是一个很神奇的东西,我们可以结合这三个例案例好好理解。

6.2 关键字参数

函数可以通过 关键字参数 的形式来调用,形如 keyword = value。例如,以下的函数:

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, "!")

接受一个必选参数 (voltage) 以及三个可选参数 (stateaction, 和 type)。可以用以下的任一方法调用:

必选参数(voltage)没有要求数据类型,所以有赋值即可。

parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword

6.3 可变参数列表

通常可变参数是参数列表的最后一个,即把剩余的输入参数传递给函数(因为无法确定可变参数列表的长度)

def lalala(*args, sep = "!"):
    return sep.join(args)

print(lalala("You", "look", 'so', 'beautiful'));

6.4 分拆参数列表

与上面刚好相反,上面是连续可变长度的参数列表,有时候我们需要传递的参数本身就是一个连续的数据类型(例如列表),但是需要调用的函数需要分开接受一个个参数值,例如列表可以用一个 * 来拆分,字典可以用 两个 ** 来拆分

>>> list(range(3, 6))            # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args))            # call with arguments unpacked from a list
[3, 4, 5]

>>> def parrot(voltage, state='a stiff', action='voom'):
...     print("-- This parrot wouldn't", action, end=' ')
...     print("if you put", voltage, "volts through it.", end=' ')
...     print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)

6.5 Lambda (短小精悍的匿名函数)

类似于嵌套函数定义,但是只能有一个单独的表达式。

>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

同时也可以作为参数传递的作用

>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值