三. 函数

Python内置了很多函数,可以直接调用。

借助抽象,我们不必关注底层的东西,直接在更高层次上思考问题。

"""
函数名称其实是指向一个函数对象的引用,完全可以把函数名赋值给另一个变量,相当于给这个函数起一个别名。
"""
a = abs
print(a(-1))#1
#print(a("a"))#TypeError: bad operand type for abs(): 'str'
#print(a(1,2))#TypeError: abs() takes exactly one argument (2 given)

 

定义函数

def my_abs(x):
    if x>=0:
        return x
    else:
        return -x
print(my_abs(-10))#10
"""
一旦执行return,结束程序
在xx.py文件目录下,打开python解释器,可以from yy import xx 
"""

def nop():
    pass#占位符,编程时使用

def my_abs(x):
    if not isinstance(x, (int,float)):#数据类型检查
        raise TypeError("错误的操作类型")
#print(my_abs("qo"))
"""
Traceback (most recent call last):
  File "D:/untitled1/base.py", line 18, in <module>
    print(my_abs("qo"))
  File "D:/untitled1/base.py", line 17, in my_abs
    raise TypeError("错误的操作类型")
TypeError: 错误的操作类型
"""

def asd(x,y):
    return x,y#多值返回,仍为单值(tuple)
x,y = asd(1,2)
z = asd(3,6)
print(x,y,z)#1 2 (3, 6)

 

"""
把参数名字和位置确定下来,函数接口定义就完成了。
调用者无需了解函数内部的复杂逻辑,只需知道如何传递正确参数,以及函数返回值即可。

"""
#位置参数,
def power(x, n):
    s = x**n
    return s
s = power(3,3)#调用函数时,传入的值按照先后位置顺序依次赋给参数x,n
print(s)#27

#默认参数
def power1(x, n=2):
    s = x**n
    return s
s1 = power1(3,4)
s2 = power1(3)
print(s1,s2)
#必选参数在前,默认参数在后;变化大的参数在前,变化小的参数在后(可作为默认参数);
#降低函数调用的难度,只有与默认参数不同的函数调用才需提供额外的信息;
def enroll(name, gender, age=9, city="bj"):
    print(name,gender,age,city)
print(enroll("w","T"))
print(enroll("w","r",10))
print(enroll("w","w",city="tj"))
"""
w T 9 bj
None
w r 10 bj
None
w w 9 tj
None
"""
def add_end(L=[]):
    L.append("END")
    return L
print(add_end())#['END']
print(add_end())#['END', 'END']

def add_end(L=None):
    if L is None:
        L=[]
    L.append("END")
    return L
print(add_end())#['END']
print(add_end())#['END']
#定义默认参数牢记一点:默认参数必须指向不变对象!(编程时,可以设计一个不变对象,尽量设计成不变对象)

#可变参数,参数数量不定
def cals(*num):#用tuple方式接收
    sum = 0
    for n in num:
        sum = sum + n
    return sum
print(cals(1,2))
print(cals())
l = [1,2,4,3]
print(cals(*l))#将l转为可变参数传入
"""
3
0
10
"""

 

"""
关键字参数
可变参数允许传入0-n个参数,这些参数在函数调用时自动组装为一个tuple,
关键字参数允许传入0-n个含参数名的参数,这些参数在函数调用时自动组装为一个dict,

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

person("n",1)
person("w",2,city="bj")
ex = {"city":"jn","job":"working"}
person("z",3,**ex)
#**ex表示把ex这个dict的所有键值对用关键字参数传入到函数的**kw参数,注意kw获得是一个拷贝
#对于可变参数,默认为tuple,本身不可变类型,无需考虑拷贝问题
"""
name n age 1 other: {}
name w age 2 other: {'city': 'bj'}
name z age 3 other: {'city': 'jn', 'job': 'working'}
"""

"""
命名关键字参数
"""
#命名关键字参数需要一个特殊分隔符*,*后面的参数视为命名关键字参数,否则系统无法识别位置参数和命名关键字参数
def child(name,age,*,city="heb",job):
    print(name,age,city,job)

child("j",24,city="bj",job="en")#j 24 bj en,必须传入参数名
child("s",2,job="wer")#s 2 heb wer 命名关键字参数可以有缺省值

#若含有可变参数,之后尾随的命名关键字参数无需*
def child1(name,age,*args,city,job):
    print(name,age,args,city,job)

child1("j",24,26,"wzc",city="bj",job="en")#j 24 (26, 'wzc') bj en

 

 

"""
参数组合:
顺序必须为:必选参数、默认参数、可变参数、命名关键字参数和关键字参数


"""
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,3)#a= 1 b= 2 c= 3 args= () kw= {}
f1(1,2,wzc="w")#a= 1 b= 2 c= 0 args= () kw= {'wzc': 'w'}
f1(1,2,3,4,"w",x=99)#a= 1 b= 2 c= 3 args= (4, 'w') kw= {'x': 99}
f2(1,2,d=99,ext=None)#a= 1 b= 2 c= 0 d= 99 kw= {'ext': None}

args = [12,3,4,6]
kw = {"x":23}
f1(*args,**kw)#a= 12 b= 3 c= 4 args= (6,) kw= {'x': 23}
args = [12,3,4,]
kw = {"d":23,"x":23}
f2(*args,**kw)#a= 12 b= 3 c= 4 d= 23 kw= {'x': 23}
"""
任意函数,都可通过func(*args,**kw)形式调用,但不要同时使用太多组合,否则接口理解性差;

"""

 

 

"""
def fact(n):
    if n == 1:
        return 1
    return n*fact(n-1)

print(fact(5))#120

递归,逻辑简单清晰,过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。
python的解释器没有针对尾递归做优化。
"""



"""
高级特性
"""
#切片
"""
L = ["w",1,2,2.3,True]
print(L[0:3],L[:3])#['w', 1, 2] ['w', 1, 2],取前n个元素
print(L[-2:],L[-2:-1])#[2.3, True] [2.3]


L1 = list(range(100))
#取出前10个和后10个
print(L1[:10],L1[-10:])#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

print(L1[11:20])#前11-20
print(L1[:10:2])#前10个,每2个取一个
print(L1[::5])#全部,每5个取一个
print(L1[:])#复制

print((0,1,2,3,4)[:3])#(0, 1, 2)

print("abcdefg"[::2])#aceg

"""

#迭代
#给定一个list 或者tuple,for循环遍历,这种遍历我们称为迭代(Iteration)
#python的for循环,可以用在其他可迭代对象上dict等
"""
d = {"a":1,"b":2,"c":3}
for key in d:
    print(key)

a
b
c
dict迭代的结果顺序可能不一样;
默认迭代key
"""
"""
for v in d.values():
    print(v)

迭代value
1
2
3
"""
"""
for k,v in d.items():
    print(k,v)

迭代k和v
a 1
b 2
c 3
"""
"""
for c in "abc":
    print(c)

a
b
c
"""
#for循环只要作用于一个可迭代对象,包括我们自定义的,只要符合迭代条件,就可以正常运作
#判断迭代对象方法
"""
from collections import Iterable
print(isinstance("abc",Iterable))#True
print(isinstance(123,Iterable))#False

for i,value in enumerate(["y","z","w"]):
    print(i,value)

0 y
1 z
2 w
enumerate把一个list变成索引-元素对
"""
"""
for tu in enumerate(["y","z","w"]):
    print(tu)

(0, 'y')
(1, 'z')
(2, 'w')
"""
"""
for x,y in [(2,3),[4,5]]:
    print(x,y)

2 3
4 5
"""

#列表生成式,List comprehensions,快速生成list
"""

print(list(range(5,7)))#[5, 6]
L = []
for x in range(3):
    L.append(x*x)
print(L)
#[0, 1, 4]

print([x*x for x in range(3)])#[0, 1, 4]
#生成的元素放前面,后面跟for循环
print([x*x for x in range(4) if x%2 == 0])#[0, 4]
print([x+y for x in range(3) for y in [3,4,5]])#[3, 4, 5, 4, 5, 6, 5, 6, 7]


import os
#查看当前目录索引文件和文件夹(目录)
print([d for d in os.listdir(".")])#['.idea', 'CNN.py', 'test', 'test-all', 'test-s', 'test.py', 'testdemo', 'train', 'train-all', 'train-s', 'traindemo', 'valid', 'valid-all', 'valid-s']

d = {"w":2,"z":1,"c":2}
print([k+"="+str(v) for k,v in d.items()])#['w=2', 'z=1', 'c=2']

L = ["HeK","EwO123","23","IBM"]
print([s.lower() for s in L])#['hek', 'ewo', 'ibm']

L = ["HeK","EwO123","23","IBM",12]
print(s.lower() for s in L if isinstance(s,str))
#<generator object <genexpr> at 0x0000020FFF5CCFC0>
print([s.lower() for s in L if isinstance(s,str)])#['hek', 'ewo123', '23', 'ibm']

"""


#生成器
#内存限制,列表容量有限,generator,生成器,可以一边循环,一边计算后续元素

#创建generator第一种方法,[列表生成式]--->(列表生成式)
g = (x for x in range(4))
print(g)#<generator object <genexpr> at 0x000001844C31AA40>
"""
for n in g:
    print(n)
    

0
1
2
3

"""

while True:
    try:
        g1 = next(g)
        print(g1)
    except StopIteration as e:
        print("end")
        break
"""
1
2
3
end
"""




#第二种方法,函数实现
def fib(max):
    n,a,b = 0,0,1
    while n<max:
        print(b)
        a,b = b,a+b#厉害
        n = n+1
    return "done"
print(fib(3))
"""
1
1
2
done
"""
#fib函数定义了推算规则,逻辑是从第一个元素推算后续任意的元素

def fib(max):
    n,a,b = 0,0,1
    while n<max:
        yield b#将print变成yield
        a,b = b,a+b#厉害
        n = n+1
    return "done"
print(fib(3))#列表生成式 <generator object fib at 0x0000020A4E153620>
#若函数定义中包含yield,函数变成generator,每次调用next时候执行,遇到yield返回,再次执行从上次返回的field语句继续执行
for n in fib(6):
    print(n)
"""
1
2
3
5
8
拿不到generator的return语句值
"""
g = fib(6)
while True:
    try:
        x = next(g)
        print(x)
    except StopIteration as e:
        print("return:",e.value)
        break
"""
1
1
2
3
5
8
return: done
"""

"""
python,可以简单的把列表生成式改成generator,也可以通过函数实现复杂的generator
generator工作原理:for循环过程中不断计算下一个元素
函数式的generator,遇到return或者执行到函数最后一行,即结束for循环
"""

 

posted on 2018-12-16 21:17  wzc521  阅读(136)  评论(0)    收藏  举报

导航