python中循环语句

Python013

python中循环语句,第1张

1、if语句

Python中的if子句由三部分组成:关键字本身、用于判断结果真假的条件表达式以及当表达式为真或者非零时执行的代码块。if 语句的语法如下:

if expression:

expr_true_suite

if 语句的expr_true_suite代码块只有在条件表达式的结果的布尔值为真时才执行,否则将继续执行紧跟在该代码块后面的语句。

(1)多重条件表达式

单个if语句可以通过使用布尔操作符and、or和not,实现多重判断条件或是否定判断条件。

(2)单一语句的代码块

如果一个复合语句(例如if子句、while或for循环)的代码块仅仅包含一行代码,那么它可以和前面的语句写在同一行上。如if make_hard_copy: send_data_to_printer(),这样的单行语句是合法的, 尽管它可能方便,但这样会使得代码更难阅读, 所以推荐将这行代码移到下一行并合理地缩进。另外一个原因就是如果你需要添加新的代码, 你还是得把它移到下一行。

2、else语句

Python提供了与if语句搭配使用的else语句,如果if语句的条件表达式的结果布尔值为假,那么程序将执行 else 语句后的代码。其语法如下:

if expression:

expr_true_suite

else:

expr_false_suite

在C语言中,不会在条件语句范围外发现else语句, 但Python不同,可以在while和for循环中使用else语句,在循环中使用时,else子句只在循环完成后执行,也就是说break语句也会跳过else块。

例:显示出10到20中的数字的最大约数

在CODE上查看代码片派生到我的代码片

#!/usr/bin/env python

def showMaxFactor(num):

count = num / 2

while count >1:

if (num % count == 0):

print 'largest factor of %d is %d' % (num, count)

break

count = count - 1

else:

pr

代码如下:

【备注】:

1. 用str.split(',')只能分隔逗号一种;如果涉及到多重分隔的话就需要使用re.split(',|:')。

2. 原字符串以逗号分隔的,后面有一个或多个字符串,所以re.split(', | ')。

3. 执行re.split(r', | ', S)操作之后,列表中会产生大量的'',就需要将filter过滤掉。

4. 使用L.count(x) == 1 或者 L.count(x) >1来保留重复项或,非重复项。

5. set(L)则是保留列表中的唯一项,再用list()将其转换为列表。

6. 使用', '.join(L),将列表拼接成我们想要的字符串。

Python类的多重继承问题深入分析

首先得说明的是,Python的类分为经典类 和 新式

经典类是python2.2之前的东西,但是在2.7还在兼容,但是在3之后的版本就只承认新式类了

新式类在python2.2之后的版本中都可以使用

经典类和新式类的区别在于:

经典类是默认没有派生自某个基类的,而新式类是默认派生自object这个基类的:

代码如下:

# old style

class A():pass

# new style

class A(obejct):pass

2.经典类在类多重继承的时候是采用从左到右深度优先原则匹配方法的..而新式类是采用C3算法(不同于广度优先)进行匹配的

3.经典类是没有__MRO__和instance.mro()调用的,而新式类是有的.

为什么不用经典类,要更换到新式类

因为在经典类中的多重继承会有些问题...可能导致在继承树中的方法查询绕过后面的父类:

代码如下:

class A():

def foo1(self):

print "A"

class B(A):

def foo2(self):

pass

class C(A):

def foo1(self):

print "C"

class D(B, C):

pass

d = D()

d.foo1()

按照经典类的查找顺序从左到右深度优先的规则,在访问d.foo1()的时候,D这个类是没有的..那么往上查找,先找到B,里面没有,深度优先,访问A,找到了foo1(),所以这时候调用的是A的foo1(),从而导致C重写的foo1()被绕过.

所以python引入了新式类的概念,每个基类都继承自object并且,他的匹配规则也从深度优先换到了C3

C3算法

C3算法是怎么做匹配的呢..在问答版块上面讨论之后,归结如下:

C3算法的一个核心是merge.

在merge列表中,如果第一个序列mro的第一个类是出现在其它序列,并且也是第一个,或者不出现其它序列,那么这个类就会从这些序列中删除,并合到访问顺序列表中

比如:(引用问题中zhuangzebo的回答@zhuangzebo)

代码如下:

class A(O):pass

class B(O):pass

class C(O):pass

class D(A,B):pass

class E(C,D):pass

首先需要知道 O(object)的mro(method resolution order)列表是[O,]

那么接下来是:

代码如下:

mro(A) = [A, O]

mro(B) = [B, O]

mro(C) = [C, O]

mro(D) = [D] + merge(mro(A), mro(B), [A, B])

= [D] + merge([A, O], [B, O], [A, B])

= [D, A] + merge([O], [B, O], [B])

= [D, A, B] + merge([O], [O])

= [D, A, B, O]

mro(E) = [E] + merge(mro(C), mro(D), [C, D])

= [E] + merge([C, O], [D, A, B, O], [C, D])

= [E, C] + merge([O], [D, A, B, O], [D])

= [E, C, D] + merge([O], [A, B, O])

= [E, C, D, A, B] + merge([O], [O])

= [E, C, D, A, B, O]

然后还有一种特殊情况:

比如:

merge(DO,CO,C) 先merge的是D

merge(DO,CO,C) 先merge的是C

意思就是.当出现有 一个类出现在两个序列的头(比如C) 这种情况和 这个类只有在一个序列的头(比如D) 这种情况同时出现的时候,按照顺序方式匹配。

新式类生成的访问序列被存储在一个叫MRO的只读列表中..

你可以使用instance.__MRO__或者instance.mro()来访问

最后匹配的时候就按照MRO序列的顺序去匹配了

C3和广度优先的区别:

举个例子就完全明白了:

代码如下:

class A(object):pass

class B(A):pass

class C(B):pass

class D(A):pass

class E(D):pass

class F(C, E):pass

按照广度优先遍历,F的MRO序列应该是[F,C,E,B,D,A]

但是C3是[F,E,D,C,B,A]

意思是你可以当做C3是在一条链路上深度遍历到和另外一条链路的交叉点,然后去深度遍历另外一条链路,最后遍历交叉点

新式类和经典类的super和按类名访问问题

在经典类中,你如果要访问父类的话,是用类名来访问的..

代码如下:

class A():

def __init__(self):

print "A"

class B(A):

def __init__(self):

print "B"

A.__init__(self) #python不会默认调用父类的初始化函数的

这样子看起来没三问题,但是如果类的继承结构比较复杂,会导致代码的可维护性很差..

所以新式类推出了super这个东西...

代码如下:

class A():

def __init__(self):

print "A"

class B(A):

def __init__(self):

print "B"

super(B,self).__init__()

这时候,又有一个问题:当类是多重继承的时候,super访问的是哪一个类呢?

super实际上是通过__MRO__序列来确定访问哪一个类的...实际上就是调用__MRO__中此类后面的一个类的方法.

比如序列为[F,E,D,C,B,A]那么F中的super就是E,E的就是D

super和按照类名访问 混合使用带来的坑

代码如下:

class A(object):

def __init__(self):

print "enter A"

print "leave A"

class B(object):

def __init__(self):

print "enter B"

print "leave B"

class C(A):

def __init__(self):

print "enter C"

super(C, self).__init__()

print "leave C"

class D(A):

def __init__(self):

print "enter D"

super(D, self).__init__()

print "leave D"

class E(B, C):

def __init__(self):

print "enter E"

B.__init__(self)

C.__init__(self)

print "leave E"

class F(E, D):

def __init__(self):

print "enter F"

E.__init__(self)

D.__init__(self)

print "leave F"

这时候打印出来是:

代码如下:

enter F

enter E

enter B

leave B

enter C

enter D

enter A

leave A

leave D

leave C

leave E

enter D

enter A

leave A

leave D

leave F

可以看出来D和A的初始化函数被乱入了两次!

按类名访问就相当于C语言之前的GOTO语句...乱跳,然后再用super按顺序访问..就有问题了

所以建议就是要么一直用super,要么一直用按照类名访问

最佳实现:

避免多重继承

super使用一致

不要混用经典类和新式类

调用父类的时候注意检查类层次

以上便是本人对于python类的继承的认识了,希望对大家能有所帮助