每天开始看python的时间越来越晚,白天写c的时候,就把python里面的单引号用上了,结过代码出现bug后,怎么也找不出了,后来发现python和c搞混了。既然付出了这么多,这一次一定要把python学好。
1.生成斐波那契数列的函数定义和调用:`
def fib(n):
a,b = 0,1
while a<n:
print(a,end=’ ')
a,b =b,a+b
print()
fib(100)
0 1 1 2 3 5 8 13 21 34 55 89 `
2.在定义函数函数时,可以在定义下加上注释,简明的说明函数的作用。
def fib(n):
‘’’ accept an integer n.
return the numbers less than n in Fibonacci sequence.’’’
a,b = 0,1
while a<n:
print(a,end= ’ ')
a,b = b,a+b
print()
fib(100)
0 1 1 2 3 5 8 13 21 34 55 89
3.Python是一种高级动态编程语音,变量类型是随时可以改变的。Python中的函数和自定义对象的也是可以随时发生改变的,可以为函数自定义对象动态增加新成员。
>>> func()
Traceback (most recent call last):
File "<pyshell#29>", line 1, in <module>
func()
File "<pyshell#28>", line 2, in func
print(func.x)
AttributeError: 'function' object has no attribute 'x'
>>> func.x =3
>>> func()
3
>>> del func.x
>>> func()
Traceback (most recent call last):
File "<pyshell#33>", line 1, in <module>
func()
File "<pyshell#28>", line 2, in func
print(func.x)
AttributeError: 'function' object has no attribute 'x'
4.函数的递归调用是函数调用的一种特殊情况,自己再调用自己,。。。,当某个条件得到满足的时候就不再调用,然后再一层一层地返回知道该函数的第一次调用。
5.在Python中,函数参数有很多种:可以为普通参数、默认值参数、关键参数、可变长度参数等等。
python 在定义函数时不需要指定形参的类型,完全由调用者传递的实参类型以及Python解释器的理解和推断来决定,类似于重载和泛型。
python函数定义也不需要指定函数的类型,这将由函数中的return语句来决定,如果没有return语句或者return没有得到执行,则认为返回空值None。
Python支持对函数参数和返回值类型的标注,但实际上并不起任何作用,只是看起来方便。
位置参数是比较常用的形式,调用函数时实参和形参的顺序必须严格一致,并且实参和形参的数量必须相同。
默认值参数必须出现在函数参数列表的最右端,且任何一个默认值参数右边不能由非默认值参数。
调用带有默认值参数的函数时,可以不对默认值参数进行赋值,也可以赋值,具有较大灵活性。
6.需要在python中特别注意的时,默认值参数只在函数定义时被接是一次。如果使用可变序列作为参数默认值是,很容易出现错误,需要在定义的函数中做出判断。
>>> def demo(newitem,old_list=None):
old_list.append(newitem)
return old_list
>>> print(demo('5',['1','2','3']))
['1', '2', '3', '5']
>>> print(demo('aaa',['a','b']))
['a', 'b', 'aaa']
>>> print(demo('a'))
['a']
>>> print(demo('b'))
['a', 'b']
先让最后一组打印结果,是不符合函数的最出设计要求的
def demo(newitem,old_list=None):
if old_list is None:
old_list = []
old_list.append(newitem)
return old_list
print(demo(‘a’))
[‘a’]print(demo(‘b’))
[‘b’]
默认值参数只在函数定义时被解释一次,可以使用“函数名.defaults”查看所有默认参数的当前值
7.可变长度参数主要有两种形式:
*parameter 用来接受多个实参并将其放在一个元组中;
**parameter 接受关键参数存放在字典中。
*parameter的用法:
def demo(*p):
print§
demo(1,2,3)
(1, 2, 3)demo(1,2)
(1, 2)demo(1,2,3,5,88)
(1, 2, 3, 5, 88)
**parameter的用法:def demo(**p):
for item in p.items():
print(item)
demo(x=1,y=2,z=3)
(‘x’, 1)
(‘y’, 2)
(‘z’, 3)
几种参数是可以混着使用的,但在一般的程序设计中,不建议这样使用。
8.传递参数时,可以通过在实参序列前加星号将其解包,然后传递给多个单变量形参。
>>> def demo(a,b,c):
print(a+b+c)
>>> seq=[1,2,3]
>>> demo(*seq)
6
>>> tup =(1,2,3)
>>> demo(*tup)
6
>>> dic = {1:'a',2:'b',3:'c'}
>>> demo(*dic)
6
>>> demo(*dic.values())
abc
>>> set = {1,2,3}
>>> demo(*set)
6
>>>
9.位置参数和系列解包可以同时使用,序列解包相当于位置参数,优先处理。
>>> def demo(a,b,c):
print(a,b,c)
>>> demo(*(1,2,3))
1 2 3
>>> demo(1,*(2,3))
1 2 3
>>> demo(a=1,*(2,3))
Traceback (most recent call last):
File "<pyshell#63>", line 1, in <module>
demo(a=1,*(2,3))
TypeError: demo() got multiple values for argument 'a'
>>> demo(b=1,*(2,3))
Traceback (most recent call last):
File "<pyshell#64>", line 1, in <module>
demo(b=1,*(2,3))
TypeError: demo() got multiple values for argument 'b'
>>> demo(c=1,*(2,3))
2 3 1
>>> demo(**{'a':1,'b':2},*(3,))#序列解包不能再关键参数解包之后
SyntaxError: iterable argument unpacking follows keyword argument unpacking
>>> demo(*(3,),**{'a':1,'b':2})
Traceback (most recent call last):
File "<pyshell#68>", line 1, in <module>
demo(*(3,),**{'a':1,'b':2})
TypeError: demo() got multiple values for argument 'a'
>>> demo(*(3,),**{'c':1,'b':2})
SyntaxError: invalid character in identifier
>>> demo(*(3,),**{'c':1,'b':2})
3 2 1
10.return语句用来从一个函数中返回一个值,同时结束函数。如果没有return语句,或者有return语句但是没有执行到,或者只有return而没有返回值,Python将认为该函数以return None结束。
因此在调用函数或对象方法时,一定要注意有没有返回值,这决定了该函数或方法分用法。
>>> a_list = [1,2,3,4,9,5,7]
>>> print(sorted(a_list))
[1, 2, 3, 4, 5, 7, 9]
>>> print(a_list)
[1, 2, 3, 4, 9, 5, 7]
>>> print(a_list.sort())
None
>>> print(a_list)
[1, 2, 3, 4, 5, 7, 9]
11.局部变量的引用比全局变量速度快,应优先考虑使用。全局变量可以分为两种情况:一个变量已在函数外定义,如果在函数内需要为这个变量赋值,并要将这个赋值结果反映到函数外,可以在函数内用global声明这个变量,将其声明为全局变量;在函数内部直接将一个变量声明为全局变量,在函数外没有声明,该函数执行后,将增加为新的全局变量。
注意:在某个作用域内只要为变量赋值的操作,该变量在这个作用域内就是局部变量,除非用global进行了声明。
>>> x =3
>>> def f():
print(x)
>>> f()
3
>>> def f():
print(x)
x = 4
print(x)
>>> f()
Traceback (most recent call last):
File "<pyshell#86>", line 1, in <module>
f()
File "<pyshell#85>", line 2, in f
print(x)
UnboundLocalError: local variable 'x' referenced before assignment
12.除了局部变量和全局变量,Python还支持nonlocal关键自定义一种介于二者之间的变量。关键字nonlocal声明的变量会引用距离最近的非全局作用域的变量,要求声明的变量已经存在,关键字nonlocal不会创建新变量。
13.lambda表达式可以用来声明匿名函数,也就是没有函数名字的临时使用的小函数,尤其适合需要一个函数作为另一个函数参数的情况。lambda表达式只可以含一个表达式,该表达式的计算结果可以看作是函数的返回值,不允许包含其它复杂的语句,但在表达式中可以调用其它函数。
def demo(n):
return n*n
>>> demo(5)
25
>>> alist = [1,2,3,4,5]
>>> list(map(lambda x:demo(x),alist))
[1, 4, 9, 16, 25]
13.编写函数,计算字符串匹配的准确率。
def Rate(origin,userInput):
if not(isinstance(origin,str) and isinstance(userInput,str)):
print("The two paremeters must be strings")
return
if len(origin)<len(userInput):
print("Sorry.I suppose the second parameter string is shorter")
return
right = 0
for origin_char,user_char in zip(origin,userInput):
if origin_char == user_char:
right += 1
return right/len(origin)
origin = "qwert ttyygf"
>>> userInput ="qwsdr eerree"
>>> print(Rate(origin,userInput))
14.编写函数,使用非递归方法对整数进行因数分解。
from random import randint
from math import sqrt
def factoring(n):
if not isinstance(n,int):
print(“You must give me an integer”)
return
result = []
for p in primes:
while n!=1:
if n%p == 0:
n=n/p
result.append§
else:
break
else:
result = ‘*’.join(map(str,result))
return result
testData = [randint(10,10000) for i in range(50)]
maxData = max(testData)
primes = [p for p in range(2,maxData) if 0 not in [p% d for d in range(2,int(sqrt§+2]]
15.编写函数模拟猜数游戏。系统随机产生一个数,玩家最多可以猜5次。系统会根据玩家的猜测进行提示,玩家则可以根据系统的提示对下一次猜测进行适当调整。
def guess(maxValue=100,maxTimes =5):
value = randint(1,maxValue)
for i in range(MaxTimes):
prompt = 'Starts to Guess:' if i==0 else 'Guess again:'
try:
x = int(input(prompt))
except:
print('Must input an integer between 1 and ',maxValue)
else:
if x == value:
print("Congratulations!")
break
elif x>value:
print('too big')
else:
print("too little")
else:
print("Game over FALL")
print("The value is ""value")
16.编写函数,计算形式 a+aa+aaa+aaaa+…+…+aaa…aaa,其中a为小于10的自然数。
def demo(v,n):
assert type(n) == int and 0<v<10,'v must be integer between 1 and 9'
result ,t = 0,0
for i in range(n):
t = t*10+v
result +=t
return result
>>> print(demo(3,4))
18.内置函数map()可以将一个函数作用到一个序列器或迭代器对象上去
19.标准库functools中的reduce()函数可以将一个接受2个参数的函数以累计的方式从左至右依次作用到一个序列或迭代器对象的所有元素上。
>>> from functools import reduce
>>> seq = [1,2,3,4,5,6,7,8,9]
>>> print((lambda x,y:x+y,seq))
(<function <lambda> at 0x0000018867A9F048>, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> print((reduce(lambda x,y:x+y,seq)))
45
>>> def add(x,y):
return x+y
>>> reduce(add,range(10))
45
>>> reduce(add,map(str,range(10)))
'0123456789'
19.内置函数filter将一个函数作用到一个序列上,返回该序列中使得该函数返回值为True的那些元素组成的filter对象。
>>> seq = ['foo','x41','?1','****']
>>> def fun(x):
return x.isalnum()
>>> list(filter(fun,seq))
['foo', 'x41']
>>> seq
['foo', 'x41', '?1', '****']
>>> [x for x in seq if x.isalnum()]
['foo', 'x41']
>>> list(filter(lambda x:x.isalnum(),seq))
['foo', 'x41']
>>>
20.包含yield语句的函数可以用来创建生成器对象,这样的函数也称为生成器函数。yield语句与return语句的作用相似,都是用来从函数中返回值。与return语句不同的是,return语句一旦执行会立刻结束函数的运行,而每次执行到yield语句并返回一个值之后会暂停或挂起后面代码的执行,下次通过生成器对象的_next_()方法、内置函数next()、for循环遍历生成器对象元素或其它方式显式“索要”数据时恢复执行。生成器具有惰性求值的特点,适合大数据处理。
>>> def f():
a,b = 1,1
while True:
yield a
a,b = b,a+b
>>> a =f()
>>> for i in range(10):
print(a._next_(),end='')
Traceback (most recent call last):
File "<pyshell#31>", line 2, in <module>
print(a._next_(),end='')
AttributeError: 'generator' object has no attribute '_next_'
>>> for i in range(10):
print(a.__next__(),end=' ')
1 1 2 3 5 8 13 21 34 55
>>> for i in f():
if i>100:
print(i,end='')
break
144
>>> a = f()
>>> next(a)
1
>>> a.__next__()
1
>>> next(a)
2
>>> a.__next__()
3
>>> def f():
yield from 'abedfs'
>>> x = f()
>>> next(x)
'a'
>>> x.__next__()
'b'
>>> next(x)
'e'
>>> for item in x:
print(item,end='')
dfs
#生成器对象支持序列解包
>>> def gen():
yield 1
yield 2
yield 3
>>> x,y,z =gen()
>>> x
1
>>> y
2
>>> z
3
21.使用dis模块可以查看函数的字节码指令
>>> import dis
>>> def add(n):
n+=1
return n
dis.dis(add)
SyntaxError: invalid syntax
>>>
>>> dis.dis(add)
2 0 LOAD_FAST 0 (x)
2 LOAD_FAST 1 (y)
4 BINARY_ADD
6 RETURN_VALUE
>>>
22.在python中函数是可以进行嵌套定义的。
>>> def myMap(iterable, op, value):
if op not in '+-*/':
return 'Error operator'
def nested(item):
return eval(repr(item)+op+repr(value))
return map(nested,iterable)
>>> list(myMap(range(5),'+',5))
[5, 6, 7, 8, 9]
>>> list(maMap(range(5),'-'5))
SyntaxError: invalid syntax
>>> list(maMap(range(5),'-',5))
Traceback (most recent call last):
File "<pyshell#85>", line 1, in <module>
list(maMap(range(5),'-',5))
NameError: name 'maMap' is not defined
>>> list(myMap(range(5),'-',5))
[-5, -4, -3, -2, -1]
>>> list(myMap(range(5),'*',5))
[0, 5, 10, 15, 20]
>>> list(myMap(range(5),'/',5))
[0.0, 0.2, 0.4, 0.6, 0.8]
23.可以使用嵌套函数定义可调用对象,任何包含__call__()方法的类的对象都是可以调用的
>>> def linear(a,b):
def result(x):
return a*x+b
return result
>>> test = linear(2,3)
>>> test(3)
9
>>> class li:
def __init__(self,a,b):
self.a,self.b = a,b
def __call__(self,x):
return self.a*x+self.b
>>> teat1 = li(2,3)
>>> teat1(3)
9
>>>
24.修饰器(decorator)是函数嵌套定义得另一个重要应用。修饰器本质也是一个函数,只不过这个函数接收其它函数作为参数并对其进行一定得改造之后返回新函数。后面中静态方法、类方法、属性等也都是通过装饰器实现得。python中还有很多这样得方法。下面演示了装饰器得定义与使用方法,定义其它函数调用之前或之后得通用代码,可作用与其它任何函数,提高代码复用度。这里有一些不明白,只是对本质进行明白,但具体应用还不是特别明白。
25.偏函数喝函数柯里化是函数编程中常用的技术。有时候我们在复用已有函数时可能需要固定其中的部分参数,这除了可以通过默认值函数来实现之外,还可以使用偏函数。
>>> def add3(a,b,c):
return a+b+c
>>> def add2(a,c):
return add3(a,666,c)
>>> print(add2(1,1))
668
>>>
也可以使用标准库functools提供的partial()方法创建指定函数的偏函数》
>>> from functools import partial
>>> add2 = partial(add3,b=666)
>>> print(add2(a=1,c=1))
668
>>>
25.函数柯里化除了可以实现偏函数类似的功能之外,还可以利用单参数函数来实现多参数函数,。
def func(a):
return lambda b:a+b
>>> print(fun(3)(5))
Traceback (most recent call last):
File "<pyshell#247>", line 1, in <module>
print(fun(3)(5))
File "<pyshell#15>", line 2, in fun
return x.isalnum()
AttributeError: 'int' object has no attribute 'isalnum'
>>> print(func(3)(5))
8
>>> def func(a):
def funcNested(b):
return a+b
return funcNested
>>>
>>> print(func(3)(5))
8
>>> def func(a):
def funcNested(b):
def funcNestedNested(c):
return a+b+c
return funcNestedNested
return funcNested
>>> print(func(3)(5)(8))
16
>>> print(func(3))
<function func.<locals>.funcNested at 0x0000018867AC7158>
后记:这次想多矫情两句,又是一个周末,回顾这周的生活,虽然有些忙碌,博客的篇数没有达到自己最初的设想。但感觉过的很充实,有女友贴心的担心和陪伴,感觉暖暖的。尽管博客篇数没有达到最初设定的目标,但这周真的没有停下来,觉得篇数不再是自己的追求,而是内容和实质。好了,我也不知道自己说的啥,总之想表达的是对于这次python 的学习一定要坚持下去。