[root@mantisbt01 python]# ./13.py
Please input your name:hadoop
Please input your height(m):1.80
Please input your height(kg):75.3
hadoop , Your bmi value is: 23.24 !
Your body type is 正常
[root@mantisbt01 python]# python
Python 3.6.4 (default, Mar 19 2018, 10:30:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.

abs(12)
12
abs(-12)
12
abs(0)
0
abs(-12.3)
12.3
abs(12.3)
12.3
abs(1,2)
Traceback (most recent call last):
File "", line 1, in
TypeError: abs() takes exactly one argument (2 given)
abs(f)
Traceback (most recent call last):
File "", line 1, in
NameError: name 'f' is not defined
max(1,2)
2
max(1,2,23,4)
23
max(1,2,23,4,-9,0)
23
int(321)
321
int(12.32)
12
float(12.32)
12.32
float(12)
12.0
float('12.32')
12.32
str(100)
'100'
str(13)
'13'
str(as)
File "", line 1
str(as)
^
SyntaxError: invalid syntax
str('as')
'as'
str('a')
'a'
str(a)
Traceback (most recent call last):
File "", line 1, in
NameError: name 'a' is not defined
bool(1)
True
bool(-1)
True
bool(0)
False
bool(a)
Traceback (most recent call last):
File "", line 1, in
NameError: name 'a' is not defined
bool('a')
True
a=abs
a(-2)
2
n1=255
n2=1000
hex(n1)
'0xff'
hex(n2)
'0x3e8'

def my_abs(x):
... if x >=0:
... return x
... else:
... return -x
...
my_abs(-9)
9
my_abs(-8)
8
my_abs(8)
8
my_abs(0)
0
my_abs(a)
Traceback (most recent call last):
File "", line 1, in
File "", line 2, in my_abs
TypeError: '>=' not supported between instances of 'builtin_function_or_method' and 'int'
my_abs('a')
Traceback (most recent call last):
File "", line 1, in
File "", line 2, in my_abs
TypeError: '>=' not supported between instances of 'str' and 'int'

[root@mantisbt01 python]# pwd
/root/python
[root@mantisbt01 python]# cat 14.py
def my_abs(x):
if x >=0:
return x
else:
return -x
[root@mantisbt01 python]# python
Python 3.6.4 (default, Mar 19 2018, 10:30:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.

from 14 import my_abs
File "", line 1
from 14 import my_abs
^
SyntaxError: invalid syntax

KeyboardInterrupt

[root@mantisbt01 python]# mv 14.py abstest.py
[root@mantisbt01 python]# python
Python 3.6.4 (default, Mar 19 2018, 10:30:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.
from abstest import my_abs
Traceback (most recent call last):
File "", line 1, in
File "/root/python/abstest.py", line 3
return x
^
TabError: inconsistent use of tabs and spaces in indentation

[root@mantisbt01 python]# vi abstest.py
[root@mantisbt01 python]# python
Python 3.6.4 (default, Mar 19 2018, 10:30:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.
from abstest import my_abs
my_abs(-18)
18
my_abs(19)
19
my_abs(0)
0
my_abs('a')
Traceback (most recent call last):
File "", line 1, in
File "/root/python/abstest.py", line 2, in my_abs
if x >=0:
TypeError: '>=' not supported between instances of 'str' and 'int'
my_abs(a)
Traceback (most recent call last):
File "", line 1, in
NameError: name 'a' is not defined

def nop():
... pass
...

if age >=18:
... pass
...
Traceback (most recent call last):
File "", line 1, in
NameError: name 'age' is not defined
age=10
if age >=18:
... age
...

my_abs(2)
2
my_abs(1,2)
Traceback (most recent call last):
File "", line 1, in
TypeError: my_abs() takes 1 positional argument but 2 were given
my_abs('A')
Traceback (most recent call last):
File "", line 1, in
File "/root/python/abstest.py", line 2, in my_abs
if x >=0:
TypeError: '>=' not supported between instances of 'str' and 'int'
abs('A')
Traceback (most recent call last):
File "", line 1, in
TypeError: bad operand type for abs(): 'str'

[root@mantisbt01 python]# cp -p abstest.py abstest2.py
[root@mantisbt01 python]#
[root@mantisbt01 python]# vi abstest2.py
[root@mantisbt01 python]# cat abstest2.py
def my_abs(x):
if not isinstance(x,(int,float)):
raise TypeError('bad operand type')
if x >=0:
return x
else:
return -x
[root@mantisbt01 python]#

[root@mantisbt01 python]# cp -p abstest.py abstest2.py
[root@mantisbt01 python]#
[root@mantisbt01 python]# vi abstest2.py
[root@mantisbt01 python]# cat abstest2.py
def my_abs(x):
if not isinstance(x,(int,float)):
raise TypeError('bad operand type')
if x >=0:
return x
else:
return -x
[root@mantisbt01 python]# python
Python 3.6.4 (default, Mar 19 2018, 10:30:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.

from abstest2 import my_abs
my_abs(-9)
9
my_abs(9)
9
my_abs(0)
0
my_abs('A')
Traceback (most recent call last):
File "", line 1, in
File "/root/python/abstest2.py", line 3, in my_abs
raise TypeError('bad operand type')
TypeError: bad operand type

import math
def move(x,y,step,angle=0):
... nx = x + step math.cos(angle)
... ny = y + step
math.sin(angle)
... return nx,ny
...
x,y=move(100,100,60,math.pi / 6)
print(x,y)
151.96152422706632 130.0
r = move(100,100,60,math.pi / 6)
print(r)
(151.96152422706632, 130.0)

r
(151.96152422706632, 130.0)

[root@mantisbt01 python]# cat 14.py
#!/usr/bin/python

#-- coding: utf-8 --

import math
def quadratic(a,b,c):
if not ( isinstance(a,(int,float)) and isinstance(b,(int,float)) and isinstance(c,(int,float)) ):
raise TypeError('bad operand type')
delta=(b*2)-(4bc)
if delta < 0:
print('delta小于零,方程无解')
else:
x1=(-b+math.sqrt(delta))/(2
a)
x2=(-b-math.sqrt(delta))/(2*a)
print('x1=%.2f x2=%.2f'%(x1,x2))
return x1,x2

print('quadratic(2,3,1)=',quadratic(2,3,1))
print('quadratic(1,3,-4)=',quadratic(1,3,-4))
[root@mantisbt01 python]# ./14.py
delta小于零,方程无解
quadratic(2,3,1)= None
x1=2.27 x2=-5.27
quadratic(1,3,-4)= (2.274917217635375, -5.274917217635375)
[root@mantisbt01 python]#

def power(x):
... return x*x
...
power(4)
16
power(2)
4
power(3)
9
power(11)
121

def power(x,n)
File "", line 1
def power(x,n)
^
SyntaxError: invalid syntax
def power(x,n):
... s=1
... while n > 0:
... n=n-1
... s=s*x
... return s
...
power(2,3)
8
power(3,3)
27
power(3,4)
81

power(5)
Traceback (most recent call last):
File "", line 1, in
TypeError: power() missing 1 required positional argument: 'n'
def power(x,n=2):
... s=1
... while n > 0:
... n=n-1
... s=sx
... return
...
power(5)
def power(x,n=2):
... s=1
... while n > 0:
... n=n-1
... s=s
x
... return s
...
power(5)
25
power(3)
9
power(3,4)
81

def enroll(name,gender):
... print('name:',name)
... print('gender:',gender)
...
enroll('Sarah','F')
name: Sarah
gender: F
def enroll(name,gender,age=6,city='Beijing'):
... print('name:',name)
... print('gender',gender)
... print('age:',age)
... print('city:',city)
...

enroll('Sarah','F')
name: Sarah
gender F
age: 6
city: Beijing
enroll('Bob','M',8)
name: Bob
gender M
age: 8
city: Beijing
enroll('Adam','M',city='shanghai')
name: Adam
gender M
age: 6
city: shanghai

def add_end(L=[]):
... L.append('END')
... return L
...
add_end([1,2,3])
[1, 2, 3, 'END']
add_end(['x','y','z'])
['x', 'y', 'z', 'END']
add_end([1,2,3])
[1, 2, 3, 'END']
add_end()
['END']
add_end()
['END', 'END']
add_end()
['END', 'END', 'END']
add_end()
['END', 'END', 'END', 'END']
def add_end(L=[]):
... if L is None:
... L=[]
... L.append('END')
... return L
...
add_end()
['END']
add_end()
['END', 'END']
add_end()
['END', 'END', 'END']
def add_end(L=None):
... if L is None:
... L=[]
... L.append('END')
... return L
...
add_end()
['END']
add_end()
['END']
add_end()
['END']

def calc(number):
... sum=0
... for n in number:
... sum=sum+n*n
... return sum
...
calc([1,2,3])
14
calc([1,2,3,4])
30
calc(1,2,3)
Traceback (most recent call last):
File "", line 1, in
TypeError: calc() takes 1 positional argument but 3 were given

def calc(number):
... sum=0
... for n in number:
... sum=sum+n
n
... return sum
...
calc(1,2,3)
14
calc([1,2,3])
Traceback (most recent call last):
File "", line 1, in
File "", line 4, in calc
TypeError: can't multiply sequence by non-int of type 'list'
calc(1,2,3,4)
30

calc(1,2)
5
calc()
0
nums = [1,2,3]
calc(nums[0],nums[1],nums[2])
14
calc(*nums)
14

关键字参数

def person(name,age,**kw):
... print('name:',name,'age:',age,'other:',kw)
...

person('Michael',30)
name: Michael age: 30 other: {}
person('Bob',35,city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
person('Adam',45,gender='M',job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

extra={'city':'Beijing','job':'Engineer'}
person('Jack',24,city=extra['city'],job=extra['job'])
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

person('Jack',24,**extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

extra表示把extra这个dict的所有key-value用关键字参数传入到函数的kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra.

命名关键字参数

def person(name,age,**kw):
... if 'city' in kw:
... pass
... if 'job' in kw:
... pass
... print('name',name,'age',age,'other:',kw)
...
person('Jack',24,city='Beijing',addr='Chaoyang',zipcode=123456)
name Jack age 24 other: {'city': 'Beijing', 'addr': 'Chaoyang', 'zipcode': 123456}

def person(name,age,*,city,job):
... print(name,age,city,job)
...
person('Jack',24,city='Beijing',job='Engineer')
Jack 24 Beijing Engineer

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:

def person(name,age,*args,city,job):
... print(name,age,args,city,job)
...
person('Jack',24,'Beijing','Engineer')
Traceback (most recent call last):
File "", line 1, in
TypeError: person() missing 2 required keyword-only arguments: 'city' and 'job'
person('Jack',24,city='Beijing','Engineer')
File "", line 1
SyntaxError: positional argument follows keyword argument
person('Jack',24,city='Beijing',job='Engineer')
Jack 24 () Beijing Engineer

命名关键字参数可以有缺省值,从而简化调用:

def person(name,age,*,city='Beijing',job):
... print(name,age,city,job)
...
由于命名关键字参数city具有默认值,调用时,可不传入city参数:
person('Jack',24,job='Engineer')
Jack 24 Beijing Engineer

参数组合

def f1(a,b,c=0,*args,**kw):
... print('a=',a,'b=',b,'c=',c,'args=',args,'kw=',kw)
...

def f2(a,b,c=0,*,d,**kw):
... print('a=',a,'b=',b,'c=',c,'d=',d,'kw=',kw)
...

f1(1,2)
a= 1 b= 2 c= 0 args= () kw= {}
f1(1,2,c=3)
a= 1 b= 2 c= 3 args= () kw= {}
f1(1,2,'a','b')
a= 1 b= 2 c= a args= ('b',) kw= {}
f1(1,2,3,'a','b')
a= 1 b= 2 c= 3 args= ('a', 'b') kw= {}
f1(1,2,3,'a','b','c')
a= 1 b= 2 c= 3 args= ('a', 'b', 'c') kw= {}
f1(1,2,3,'a','b','c',x=98)
a= 1 b= 2 c= 3 args= ('a', 'b', 'c') kw= {'x': 98}

f2(1,2,d=23,ext=None)
a= 1 b= 2 c= 0 d= 23 kw= {'ext': None}

通过一个tuple和dict,也可以调用上述函数:

args=(1,2,3,4)

kw={'d':99,'x':'#'}

f1(*args,**kw)
a= 1 b= 2 c= 3 args= (4,) kw= {'d': 99, 'x': '#'}

f2(*args,**kw)
Traceback (most recent call last):
File "", line 1, in
TypeError: f2() takes from 2 to 3 positional arguments but 4 positional arguments (and 1 keyword-only argument) were given

args=(1,2,3)

kw={'d':88,'x':'#'}

f2(*args,**kw)
a= 1 b= 2 c= 3 d= 88 kw= {'x': '#'}

[root@mantisbt01 python]# cat ./15.py
#!/usr/bin/python

#-- coding:utf-8 --

def product(numbers):
product=1
if numbers==():
raise TypeError
else:
for n in numbers:
product=product
n

print('product =',product)

    return product

#test
print('product(5) =',product(5))
print('product(5,6) =',product(5,6))
print('product(5,6,7) =',product(5,6,7))
print('product(5,6,7,9) =',product(5,6,7,9))

if product(5) != 5:
print('test failed!')
elif product(5,6) != 30:
print('test failed!')
elif product(5,6,7) != 210:
print('test failed!')
elif product(5,6,7,9) != 1890:
print('test failed!')
else:
try:
product()
print('test failed!')
except TypeError:
print('test successful')
[root@mantisbt01 python]# ./15.py
product(5) = 5
product(5,6) = 30
product(5,6,7) = 210
product(5,6,7,9) = 1890
test successful
[root@mantisbt01 python]#

递归函数

def fact(n):
... if n==1:
... return 1
... return n*fact(n-1)
...
fact(1)
1
fact(5)
120
fact(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
fact(1000)
Traceback (most recent call last):
File "", line 1, in
File "", line 4, in fact
File "", line 4, in fact
File "", line 4, in fact
[Previous line repeated 994 more times]
File "", line 2, in fact
RecursionError: maximum recursion depth exceeded in comparison

[root@mantisbt01 python]# python
Python 3.6.4 (default, Mar 19 2018, 10:30:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.

def fact(n):
... return fact_iter(n,1)
...
def fact_iter(num,product):
... if num==1:
... return product
... return fact_iter(num-1,num*product)
...
fact_iter(5,1)
120
fact_iter(10,1)
3628800
fact_iter(1,1)
1
fact_iter(20,1)
2432902008176640000
fact_iter(1000,1)
Traceback (most recent call last):
File "", line 1, in
File "", line 4, in fact_iter
File "", line 4, in fact_iter
File "", line 4, in fact_iter
[Previous line repeated 994 more times]
File "", line 2, in fact_iter
RecursionError: maximum recursion depth exceeded in comparison

fact(10)
3628800
def fact(n):
... s=1
... for i in range(1,n+1):
... s=si
... return s
...
fact(10)
3628800
fact(5)
120
from functools import reduce
def Fact(n):
... return reduce((lambda x,y:x
y),list(range(1,n+1)))
...
Fact(5)
120
Fact(10)
3628800

汉诺塔的移动可以用递归函数非常简单地实现。

请编写move(n, a, b, c)函数,它接收参数n,表示3个柱子A、B、C中第1个柱子A的盘子数量,然后打印出把所有盘子从A借助B移动到C的方法,例如:
[root@mantisbt01 python]# cat ./17.py
#!/usr/bin/python

#-- coding:utf-8 --

def move(n,a,b,c):
if n==1:
step=1
print(a,'-->',c)
return step
else:
s1=move(n-1,a,c,b)
s2=move(1,a,b,c)
s3=move(n-1,b,a,c)
step=s1+s2+s3
return step

s=move(3,'A','B','C')
print('need %d steps'%s)
[root@mantisbt01 python]# ./17.py
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C
need 7 steps
[root@mantisbt01 python]#

高级特性
比如构造一个1, 3, 5, 7, ..., 99的列表,可以通过循环实现:

L = []
n = 1
while n <= 99:
L.append(n)
n = n + 2
取list的前一半的元素,也可以通过循环实现。

但是在Python中,代码不是越多越好,而是越少越好。代码不是越复杂越好,而是越简单越好。

基于这一思想,我们来介绍Python中非常有用的高级特性,1行代码能实现的功能,决不写5行代码。请始终牢记,代码越少,开发效率越高。
法1:

L=[]
n=1
while n<=99:
... L.append(n)
... n=n+2
...
L
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]

法2:

print(list(range(1,100,2)))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]

法3:

print([i for i in range(1,100,2)])
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]

1.切片
1.1 list

L=['Michael','Sarah','Tracy','Bob','Jack']
[L[0],L[1],L[2]]
['Michael', 'Sarah', 'Tracy']
[L[-1],L[-2],L[-3]]
['Jack', 'Bob', 'Tracy']
r=[]
n=3
for i in range(n):
... r.append(L[i])
...
r
['Michael', 'Sarah', 'Tracy']
L[0:3]
['Michael', 'Sarah', 'Tracy']
L[0:4]
['Michael', 'Sarah', 'Tracy', 'Bob']
L[1:3]
['Sarah', 'Tracy']
L[:3]
['Michael', 'Sarah', 'Tracy']
L[-2:]
['Bob', 'Jack']
L[-2:-1]
['Bob']
L[-1]
'Jack'
L=list(range(100))
L
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
L[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
L[-10:]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
L[10:20]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
L[2:10:2]
[2, 4, 6, 8]
L[2:10:3]
[2, 5, 8]
L[::5]
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
L[:]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

1.2 tuple

(0,1,2,3,4,5)[:3]
(0, 1, 2)
'ABCDEFG'[:3]
'ABC'
'ABCDEFG'[::2]
'ACEG'

利用切片操作,实现一个trim()函数,去除字符串首尾的空格,注意不要调用str的strip()方法:
[root@mantisbt01 python]# cat 18.py
#!/usr/bin/python

#-- coding:utf-8 --

#def trim(s):

if len(s) == 0:

return s

elif s[0] == '':

return (trim(s[1:]))

elif s[-1] == ' ':

return (trim(s[:-1]))

return s

def trim(s):
if s[:1] != ' ' and s[-1:] != ' ':
return s
elif s[:1] == ' ':
return trim(s[1:])
else:
return trim(s[:-1])

if trim('hello ') != 'hello':
print('测试失败!')
elif trim(' hello') != 'hello':
print('测试失败!')
elif trim(' hello ') != 'hello':
print('测试失败!')
elif trim(' hello world ') != 'hello world':
print('测试失败!')
elif trim('') != '':
print('测试失败!')
elif trim(' ') != '':
print('测试失败!')
else:
print('测试成功!')
[root@mantisbt01 python]# ./18.py
测试成功!

2.迭代

d={'a':1,'b':2,'c':3}
for key in d:
... print(key)
...
a
b
c
for ch in 'ABC':
... print(ch)
...
A
B
C

from collections import Iterable
isinstance('abc',Iterable)
True
isinstance([1,2,3],Iterable)
True
isinstance(123,Iterable)
False

for i,value in enumerate(['A','B','C']):
... print(i,value)
...
0 A
1 B
2 C
for x,y in [(1,1),(2,4),(3,9)]:
... print(x,y)
...
1 1
2 4
3 9

请使用迭代查找一个list中最小和最大值,并返回一个tuple:
使用冒泡排序法
[root@mantisbt01 python]# cat 19.py
#!/usr/bin/python

#-- coding:utf-8 --

def findMinandMax(L):
if (L==[]):
return (None,None)
else:
num=len(L)
for i in range(num):
for j in range(i):
if L[i]L[i],L[j]=L[j],L[i]
return (L[0],L[-1])

if findMinandMax([]) != (None,None):
print('测试失败!')
elif findMinandMax([7]) != (7,7):
print('测试失败!')
elif findMinandMax([7,1]) != (1,7):
print('测试失败!')
elif findMinandMax([7,1,3,9,5]) != (1,9):
print('测试失败!')
else:
print('测试成功')
[root@mantisbt01 python]#
[root@mantisbt01 python]# ./19.py
测试成功

3.列表生成式

list(range(1,11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
L=[]
for x in range(1,11):
... L.append(xx)
...
L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[x
x for x in range(1,11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

[x*x for x in range(1,11) if x%2 == 0]
[4, 16, 36, 64, 100]

[m+n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

import os
[d for d in os.listdir('.')]
['18.py', '19.py', '1.py', '2.py', '3.py', '4.py', '5.py', '6.py', '7.py', '8.py', '9.py', '10.py', '11.py', '12.py', '13.py', 'abstest.py', 'pycache', 'abstest2.py', '14.py', '15.py', '16.py', '17.py']

[d for d in os.listdir('/')]
['boot', 'dev', 'proc', 'run', 'sys', 'etc', 'root', 'var', 'tmp', 'usr', 'bin', 'sbin', 'lib', 'lib64', 'home', 'media', 'mnt', 'opt', 'srv', '.autorelabel']

[d for d in os.listdir('/home')]
['test2', 'test3', 'test4', 'test1']

d={'x':'A','y':'B','z':'C'}
for k,v in d.items():
... print(k,'=',v)
...
x = A
y = B
z = C

d={'x':'A','y':'B','z':'C'}
[k+'='+v for k,v in d.items()]
['x=A', 'y=B', 'z=C']
L=['Hello','World','IBM','Apple']
[s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']

L=['Hello','World',18,'IBM','Apple']
[s.lower() for s in L]
Traceback (most recent call last):
File "", line 1, in
File "", line 1, in
AttributeError: 'int' object has no attribute 'lower'

[root@mantisbt01 python]# cat 20.py
#!/usr/bin/python

#-- coding:utf-8 --

L1=['Hello','World',18,'IBM',None]
L2=[s.lower() for s in L1 if isinstance(s,str)]

print(L2)
if L2 == ['hello','world','ibm']:
print('测试通过!')
else:
print('测试失败')
[root@mantisbt01 python]# ./20.py
['hello', 'world', 'ibm']
测试通过!
[root@mantisbt01 python]#

4.生成器

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

g=(x*x for x in range(10))
g
at 0x7f8ab91c8570>
next(g)
0
next(g)
1
next(g)
4
next(g)
9
next(g)
16
next(g)
25
next(g)
36
next(g)
49
next(g)
64
next(g)
81
next(g)
Traceback (most recent call last):
File "", line 1, in
StopIteration

g=(x*x for x in range(10))
for n in g:
... print(n)
...
0
1
4
9
16
25
36
49
64
81
def fib(max):
... n,a,b=0,0,1
... while n < max:
... print(b)
... a,b=b,a+b
... n=n+1
... return 'done'
...
fib(6)
1
1
2
3
5
8
'done'

def fib(max):
... n,a,b=0,0,1
... while n < max:
... yield b
... a,b=b,a+b
... n=n+1
... return 'done'
...
f=fib(6)
f

def odd():
... print('step 1')
... yield 1
... print('step 2')
... yield(3)
... print('step 3')
... yield(5)
...
o=odd()
next(o)
step 1
1
next(o)
step 2
3
next(o)
step 3
5
next(o)
Traceback (most recent call last):
File "", line 1, in
StopIteration
for n in fib(6):
... print(n)
...
1
1
2
3
5
8
g=fib(6)
while True:
... try:
... x=next(g)
... print('g:',x)
... except StopIteration as e:
... print('Generator return value:',e.value)
... break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done

练习

[root@mantisbt01 python]# cat ./21.py
#!/usr/bin/python

#-- coding:utf-8 --

def triangles():
L=[1]
while True:
yield L
L = [x+y for x,y in zip([0]+L,L+[0])]

n = 0
results = []
for t in triangles():
print(t)
results.append(t)
n = n + 1
if n == 10:
break
if results == [
[1],
[1, 1],
[1, 2, 1],
[1, 3, 3, 1],
[1, 4, 6, 4, 1],
[1, 5, 10, 10, 5, 1],
[1, 6, 15, 20, 15, 6, 1],
[1, 7, 21, 35, 35, 21, 7, 1],
[1, 8, 28, 56, 70, 56, 28, 8, 1],
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
]:
print('测试通过!')
else:
print('测试失败!')
[root@mantisbt01 python]# ./21.py
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
测试通过!
[root@mantisbt01 python]# cat ./22.py
#!/usr/bin/python

#-- coding:utf-8 --

def triangles():
L=[1]
while True:
yield L
L = [x+y for x,y in zip([0]+L,L+[0])]

n = 0
results = []
for t in triangles():
print(t)
results.append(t)
n = n + 1
if n == 15:
break
[root@mantisbt01 python]# ./22.py
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1]
[1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1]
[1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1]
[1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1]
[1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1]
[root@mantisbt01 python]#

from collections import Iterable
isinstance([],Iterable)
True
isinstance({},Iteranle)
Traceback (most recent call last):
File "", line 1, in
NameError: name 'Iteranle' is not defined
from collections import Iterable
isinstance([],Iterable)
True
isinstance({},Iterable)
True
isinstance('abc',Iterable)
True
isinstance(x for x in range(10),Iterable)
File "", line 1
SyntaxError: Generator expression must be parenthesized if no t sole argument
isinstance((x for x in range(10)),Iterable)
True
isinstance(100,Iterable)
False

from collections import Iterator
isinstance((x for x in range(10)),Iterator)
True
isinstance([],Iterator)
False
isinstance({},Iterator)
False
isinstance('ABC',Iterator)
False
isinstance(100,Iterator)
False
isinstance(iter([]),Iterator)
True
isinstance(iter('abc'),Iterator)
True

for x in [1,2,3,4,5]:
... pass
...
for x in [1,2,3,4,5]:
... print(x)
...
1
2
3
4
5

it=iter([1,2,3,4,5])
while True:
... try:
... x=next(it)
... print(x)
... except StopIteration:
... break
...
1
2
3
4
5

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

函数式编程

函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。

函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!

Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

1.高阶函数

传入函数
既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

一个最简单的高阶函数:

abs

abs(-10)
10
x=abs(-2)
x
2
f=abs
f

f(-2)
2
abs=10
abs
10
abs(-2)
Traceback (most recent call last):
File "", line 1, in
TypeError: 'int' object is not callable

[root@mantisbt01 python]# python
Python 3.6.4 (default, Mar 19 2018, 10:30:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.

abs(-2)
2
f(-2)
Traceback (most recent call last):
File "", line 1, in
NameError: name 'f' is not defined
f=abs
f(-2)
2
def add(x,y,f):
... return f(x) + f(y)
...
print(add(-5,6,abs))
11

map\reduce

abs(-2)
2
f(-2)
Traceback (most recent call last):
File "", line 1, in
NameError: name 'f' is not defined
f=abs
f(-2)
2
def add(x,y,f):
... return f(x) + f(y)
...
print(add(-5,6,abs))
11

def f(x):
... return x*x
...
r=map(f,[1,2,3,4,5,6,7,8,9])
list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
r

L=[]
for n in [1,2,3,4,5,6,7,8,9]:
... L.append(f(n))
...
print(L)
[1, 4, 9, 16, 25, 36, 49, 64, 81]

from functools import reduce
def add(x,y):
... return x+y
...
reduce(add,[1,3,5,7,9])
25

from functools import reduce
def fn(x,y):
... return x*10+y
...
reduce (fn,[1,3,5,7,9])
13579

from functools import reduce
def fn(x,y):
... return x*10+y
...
def char2num(s):
... digits = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
... return digits[s]
...
reduce (fn,map(char2num,'13579'))
13579

整理成一个函数

from functools import reduce
DIGITS = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
def str2int(s):
... def fn(x,y):
... return x*10+y
... def char2num(s):
... return DIGITS[s]
... return reduce(fn,map(char2num,s))
...
print(str2int('13579'))
13579

from functools import reduce
DIGTS={'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
def char2sum(s):
... return DIGITS[s]
...
def str2int(s):
... return reduce(lambda x,y:x*10+y,map(char2num,s))
...

str2int('13579')
13579
str2int('1239')
1239

利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']:

def normalize(name):
... name=name[0].upper()+name[1:].lower()
... return name
...
L1=['adam','LISA','BarT']
Ls=list(map(normalize,L1))
print(Ls)
['Adam', 'Lisa', 'Bart']

def normalize2(name):
... name=name.lower()
... name=name.upper()
... return name
...
L1=['adam','LISA','BarT']
L2=list(map(normalize2,L1))
print(L2)
['ADAM', 'LISA', 'BART']

def normalize3(name):
... return name.capitalize()
...
L2=list(map(normalize3,L1))
print(L2)
['Adam', 'Lisa', 'Bart']
L1=['adam','LISA','BarT']
L2=list(map(normalize3,L1))
print(L2)
['Adam', 'Lisa', 'Bart']

Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积:

def prod(L):
... def fn(x,y):
... return xy
... return reduce(fn,L)
...
print('3
579=',prod([3,5,7,9]))
357*9= 945
if prod([3,5,7,9])==945:
... print('测试成功!')
... else:
... print('测试失败!')
...
测试成功!

利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456:

from functools import reduce
def str2float(s):
... def fn(x,y):
... return x*10+y
... n=s.index('.')
... s1=list(map(int,[x for x in s[:n]]))
... s2=list(map(int,[x for x in s[n+1:]]))
... return reduce(fn,s1) + reduce(fn,s2)/10**len(s2)
... print('str2float(\'123.456\') =', str2float('123.456'))
...

print('str2float(\'123.456\') =', str2float('123.456'))
str2float('123.456') = 123.456

if abs(str2float('123.456') - 123.456) < 0.00001:
... print('测试成功!')
... else:
... print('测试失败!')
...
测试成功!

print('str2float(\'1.43\') =', str2float('1.43'))
str2float('1.43') = 1.43

filter

用filter求素数
计算素数的一个方法是埃氏筛法,它的算法理解起来非常简单:

首先,列出从2开始的所有自然数,构造一个序列:

2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

取序列的第一个数2,它一定是素数,然后用2把序列的2的倍数筛掉:

3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

取新序列的第一个数3,它一定是素数,然后用3把序列的3的倍数筛掉:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

取新序列的第一个数5,然后用5把序列的5的倍数筛掉:

7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

不断筛下去,就可以得到所有的素数。

def is_odd(n):
... return n%2 ==1
...
list(filter(is_odd,[1,2,4,6,9,10]))
[1, 9]
list(filter(is_odd,[1,2,4,5,6,9,10,15]))
[1, 5, 9, 15]

def not_empty(s):
... return s and s.strip()
...
list(filter(not_empty,['A','','B',None,'C',' ']))
['A', 'B', 'C']

def _odd_iter():
... n=1
... while True:
... n=n+2
... yield n
...

def primes():
... yield 2
... it = _odd_iter()
... while True:
... n=next(it)
... yield n
... it=filter(_not_divisible(n),it)
...

for n in primes():
... if n < 1000:
... print(n)
... else:
... break
...
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
103
107
109
113
127
131
137
139
149
151
157
163
167
173
179
181
191
193
197
199
211
223
227
229
233
239
241
251
257
263
269
271
277
281
283
293
307
311
313
317
331
337
347
349
353
359
367
373
379
383
389
397
401
409
419
421
431
433
439
443
449
457
461
463
467
479
487
491
499
503
509
521
523
541
547
557
563
569
571
577
587
593
599
601
607
613
617
619
631
641
643
647
653
659
661
673
677
683
691
701
709
719
727
733
739
743
751
757
761
769
773
787
797
809
811
821
823
827
829
839
853
857
859
863
877
881
883
887
907
911
919
929
937
941
947
953
967
971
977
983
991
997

回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()筛选出回数:

def is_palindrome(n):
... if str(n)==str(str(n)[::-1]):
... return n
...
out=filter(is_palindrome,range(1,1000))

print('1~1000:',list(out))
1~1000: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999]
out=filter(is_palindrome,range(1,200))
print('1~200:',list(out))
1~200: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]

貌似不能判断最后一个元素

out=filter(is_palindrome,1)
Traceback (most recent call last):
File "", line 1, in
TypeError: 'int' object is not iterable
out=filter(is_palindrome,range(1))
print('1:',list(out))
1: []
out=filter(is_palindrome,range(1,2))
print('1:',list(out))
1: [1]
out=filter(is_palindrome,range(1,3))
print('1~3:',list(out))
1~3: [1, 2]
out=filter(is_palindrome,range(1,11))
print('1~3:',list(out))
1~3: [1, 2, 3, 4, 5, 6, 7, 8, 9]
out=filter(is_palindrome,range(1,12))
print('1~3:',list(out))
1~3: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

法2

def is_palindrome(n):
... a=list(str(n))
... b=list(str(n))
... b.reverse()
... return a==b
...

out=filter(is_palindrome,range(1,11))
print('1~3:',list(out))
1~3: [1, 2, 3, 4, 5, 6, 7, 8, 9]
out=filter(is_palindrome,range(1,12))
print('1~3:',list(out))
1~3: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

a=range(1,5)
a
range(1, 5)
list(a)
[1, 2, 3, 4]

sorted

sorted([2,4,-6,21,9])
[-6, 2, 4, 9, 21]
sorted([2,4,-6,21,-9])
[-9, -6, 2, 4, 21]
sorted([2,4,-6,21,-9,0])
[-9, -6, 0, 2, 4, 21]
sorted([2,4,-6,21,-9,0],key=abs)
[0, 2, 4, -6, -9, 21]
sorted(['Bob','about','Zoo','Credit','kel'])
['Bob', 'Credit', 'Zoo', 'about', 'kel']

sorted(['bob','about','Zoo','Credit'],key=str.lower)
['about', 'bob', 'Credit', 'Zoo']

sorted(['bob','about','Zoo','Credit'],key=str.lower,reverse=True)
['Zoo', 'Credit', 'bob', 'about']

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

按分数排序

sorted(L,key=lambda x:x[1])
[('Bart', 66), ('Bob', 75), ('Lisa', 88), ('Adam', 92)]

按名字排序

sorted(L,key=lambda x:x[0])
[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]