python 惰性序列_python 基础(三)

本文介绍了Python函数的基础概念,包括定义、调用、参数传递、返回值及递归等内容,并探讨了函数式编程的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数调用

定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。

这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。

如下实例调用了 printme() 函数:

#!/usr/bin/python3

# 定义函数

defprintme(str):

# 打印任何传入的字符串

print(str)

return# 调用函数

printme("我要调用用户自定义函数!")

printme("再次调用同一函数")

以上实例输出结果:

我要调用用户自定义函数!再次调用同一函数函数特性:

减少重复代码

使程序变的可扩展

使程序变得易维护

参数 :

必须参数 ---》

--必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

def t1(x):

print(x)

t1(2) # 必须传入一个参数 否则不传入参数会运行报错

输出结果 2

关键字参数 ---》

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

实例:

deft2(**kwargs):

print(kwargs)

t2(name='tom',age=28,sex='N')

t2(**{'name': 'jony','sex': 'F’})

输出结果为:

{'name': 'tom', 'sex': 'N', 'age': 28}

{'name': 'jony', 'sex': 'F'}

默认参数

调用函数时,如果没有传递参数,则会使用默认参数。

实例;

def t(x, y=2):

print(x)

print(y)

t(1)

t(1,3) #1,3 是位置参数也是实参 与形参一一对应

输出结果:

x 是形参  y为默认参数

1

2

1

3

不定长参数

你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明时不会命名。如下:

deft3(*args):

print(args)

t3(10,20,30,50,80)

输出结果:(10, 20, 30, 50, 80) #元组

加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数

#*args接受N个位置参数,转化成元组;

#**kwargs接收N个关键字参数,转为字典

#位置参数必须放在关键字参数前面

#关键字与形参顺序无关

def test(x,y,z):

print(x)

print(y)

print(z)

# test(y=2,x=1) #与形参顺序无关

# test(1,2) #与形参一一对应

#test(x=2,3)

test(3,z=2,y=6)

全局与局部变量:全局变量和局部变量的区别在于作用域,全局变量在整个py文件中声明,全局范围内可以使用;局部变量是在某个函数内部声明的,只能在函数内部使用,如果超出使用范围(函数外部),则会报错。

当全局变量与局部变量同名时:(在函数内部,如果局部变量与全局变量变量名一样,则优先调用局部变量。)在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。

实例

school = ‘old boy’  # 全局变量

def change_name(name):

print(“before change ”,name,school)

name=’kk’   #这个函数就是这个变量的作用域 也就是说在此函数内生效

print(“after change ”,name)

name=’gg’

chang_name(name)

print(name)

输出结果为:

before change gg mage

after change kk

gg old boy

school = 'old boy' # 全局变量

name='gg'

def change_name(name):

global school # 声明局部变量改为全局变量

school = 'mage'

print("before change ",name,school)

name='kk' #这个函数就是这个变量的作用域 也就是说在此函数内生效

print("after change ",name)

#name='gg'

change_name(name)

print(name,school)

输出结果;

before change gg mage

after change kk

gg mage

返回值

函数的最后都有一个返回值return,可以用来获取该函数执行结果返回给该函数,让外部调用该函数的根据返回的值不同做不同的事。

返回值可指定,如果不指定默认返回None

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

def test1():

print('alex')

print(test1())

def test2():

a= 5

if a <5:

return True

else:

return False

print(test2())

#根据返回的值进行其他判断

if test2():

print('yes')

else:

print('no')

结果:

alex

None

False

no

函数遇到return后就结束,该函数return下还有多少代码都不执行

函数可以返回多个值

结果:

(1, 2)

返回多值其实就是返回一个tuple,在语法上返回一个tuple可以省略括号

也可以返回列表

结果:

[1, 2]

递归函数:

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

递归函数特性:

必须有一个明确的结束条件;

每次进入更深一层递归时,问题规模相比上次递归都应有所减少

相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)。

递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

实例:

def calc ( n ):

print(n)

if int(n/2)==0:

return n

return calc(int (n /2)) # 函数递归

calc(10)

输出结果:

10

5

2

1

递归实现三级菜单练习

#!/usr/bin/env python

# -*- coding: UTF-8 -*-

menu = {

'北京': {

'海淀': {

'五道口': {

'soho': {},

'网易': {},

'google': {}

},

'中关村': {

'爱奇艺': {},

'汽车之家': {},

'youku': {},

},

'上地': {

'百度': {},

},

},

'昌平': {

'沙河': {

'老男孩': {},

'北航': {},

},

'天通苑': {},

'回龙观': {},

},

'朝阳': {},

'东城': {},

},

'上海': {

'闵行': {

"人民广场": {

'炸鸡店': {}

}

},

'闸北': {

'火车战': {

'携程': {}

}

},

'浦东': {},

},

'山东': {},

}

exit_flag = False

l = [menu]

# k= input('input>>').strip()

# print (l[-1][k]) # {'浦东': {}, '闸北': {'火车战': {'携程': {}}}, '闵行': {'人民广场': {'炸鸡店': {}}}}

# print (l[-1].keys()) # (['山东', '北京', '上海']

while not exit_flag:

for key in l[-1]:

print(key)

k = input('input>>').strip() # 北京

if k in l[-1].keys() and l[-1][k]:

l.append(l[-1][k])

elif k == 'b':

l.pop()

elif k == 'q':

exit_flag =True

else:

print( "输入错误,请重新输入")

二分查找法

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

print(l.index(66))

输出结果: 17 #(index=17)

匿名函数

匿名函数就是不需要显式的指定函数名。

关键字lambda表示匿名函数,冒号前面的n表示函数参数,可以有多个参数。

匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:

有些函数在代码中只用一次,而且函数体比较简单,使用匿名函数可以减少代码量,看起来比较"优雅“

实例

#这段代码

def calc(x,y):

return x**y

#换成匿名函数

calc = lambda x,y:x**y

print(calc(2,5))

输出结果 32

函数式编程:

函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。

函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。

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

一、定义

简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。

主要思想是把运算过程尽量写成一系列嵌套的函数调用。举例来说,现在有这样一个数学表达式:

(1 + 2) * 3 - 4

传统的过程式编程,可能这样写:

var a = 1 + 2;

var b = a * 3;

var c = b - 4;

函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:

var result = subtract(multiply(add(1,2), 3), 4);

这段代码再演进以下,可以变成这样

add(1,2).multiply(3).subtract(4)

这基本就是自然语言的表达了。再看下面的代码,大家应该一眼就能明白它的意思吧:

merge([1,2],[3,4]).sort().search("2")

因此,函数式编程的代码更容易理解。

要想学好函数式编程,不要玩py,玩Erlang,Haskell, 好了,我只会这么多了。。

面向对象和面向过程

面向对象---》类---》class

面向过程---》过程---》def

函数式编程---》函数---》def

高阶函数:

一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。

实例

#参数为函数

def bar():

print("in the bar..")

def foo(func):

func()

print("in the foo..")

foo(bar)

输出结果;

in the bar..

in the foo..

#返回值为函数

def bar():

print("in the bar..")

def foo(func):

print("in the foo..")

return bar

res=foo(bar)

print(res)

print(res())

输出结果 :

in the foo..

in the bar..

None

#返回值为函数

def bar():

print("in the bar..")

def foo(func):

print("in the foo..")

return bar

res=foo(bar)

res()

以上两个示例中,函数foo()为高阶函数,示例一中函数bar作为foo的参数传入,示例二中函数bar作为foo的返回值。

注:函数名(例如bar 、foo)-->其为该函数的内存地址;函数名+括号(例如 bar()、foo() )-->调用该函数。

高阶函数-map、filter、reduce

这三个函数均为高阶函数,其也为Python内置的函数

map函数

map函数接收的是两个参数,一个函数,一个序列,其功能是将序列中的值处理再依次返回至列表内

实例:

map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。

filter函数

filter函数也是接收一个函数和一个序列的高阶函数,其主要功能是过滤。其返回值也是迭代器对象

reduce函数

reduce函数也是一个参数为函数,一个为可迭代对象的高阶函数,其返回值为一个值而不是迭代器对象,故其常用与叠加、叠乘等

实例:

或:

from functools import reduce # 高阶函数

def add(x,y):

return x + y

t=reduce(add,(1,4,5,7,9))

print(t)

输出结果:26

内置函数:

注:查看详细猛击这里

abs() 对传入参数取绝对值

bool() 对传入参数取布尔值, None, 0, "",[],{},() 这些参数传入bool后,返回False

all() 所有传入参数为真,才为真

any() 任何一个传入参数为真,才为真

ascii() 自动执行传入参数的_repr_方法(将对象转换为字符串)

bin() 接收一个十进制,转换成二进制

oct() 接收一个十进制,转换成八进制

hex() 接收一个十进制,转换成十六进制

bytes() 字符串转换成字节。第一个传入参数是要转换的字符串,第二个参数按什么编码转换为字节 eg. bytes(s,encoding = 'utf-8') , bytes(s,encoding = 'gbk')    1个字节占8位;utf-8编码格式下,一个汉字占3个字节;gbk编码格式下,一个汉字占2个字节

str() 字节转换成字符串。第一个传入参数是要转换的字节,第二个参数是按什么编码转换成字符串

chr(65)  # 数字转字母,查看ASCII码表

ord('A')  # 字母转数字,查看ASCII码表

compile()  # 接收.py文件或字符串作为传入参数,将其编译成python字节码

eval()    # 执行python代码,并返回其执行结果。 e.g. eval("1+2+3")   eval("print(123)").   在接收用户输入时应避免使用eval,因为别有用心的用户可能借此注入恶意代码

exec()    #执行python代码(可以是编译过的,也可以是未编译的),没有返回结果(返回None) e.g. exec(compile("print(123)","","exec"))   exec("print(123)")

dir()  # 接收对象作为参数,返回该对象的所有属性和方法

help()  # 接收对象作为参数,更详细地返回该对象的所有属性和方法

divmod(100,10)  # 返回一个元组(10,0),第一个元素的100/10的商,第二个元素的100/10的余数

enumerate()  # 接收序列化类型的数据,返回一个迭代器(对象). e.g. for i,item in enumerate(['one','two','three']): print(i,item)  打印1 'one' 换行2 'two'换行 3 'three'

isinstance(object, class)  # 判断对象是否是某个类的实例. e.g. isinstance([1,2,3],list)

filter(函数或者lambda表达式,可迭代的对象)  # 对可迭代对象中的每一个元素,将其作为实参传入函数(或lambda表达式),如果函数返回False,将该元素丢弃,如果函数返回True,将该元素添加到filter的返回值中。注意filter返回的是一个filter对象,实际应用中往往需要用list或tuple将其转换为列表或元组类型. e.g. list(filter(lambda a:a>1,[1,2,3])) 返回[2,3]

map(函数或lambda表达式,可迭代的对象)  #对可迭代的每一个元素,将其作为实参传入函数,将每一次调用函数返回的结果都添加到map的返回值中。e.g. tuple(map(lambda a:a+1,(1,2,3))) 返回(2,3,4)

format()  #字符串格式化

frozenset()  #转换为不可变的集合

globals()  # 返回一个字典,包括所有的全局变量与它的值所组成的键值对

locals()  # 返回一个字典,包括所有的局部变量与它的值所组成的键值对

hash()  # 对传入参数取哈希值并返回

id() # 返回内存地址,可用于查看两个变量是否指向相同一块内存地址

input('please input:')  # 提示用户输入,返回用户输入的内容(不论输入什么,都转换成字符串类型)

issubclass(subclass,class) #查看这个类是否是另一个类的派生类,如果是返回True,否则返回False

len('string')  # 返回字符串长度,在python3中以字符为单位,在python2中以字节为单位

max()  #接收序列化类型数据,返回其中值最大的元素

min()  # ..... 返回其中值最小的元素

memoryview()  # 查看内存地址

next()

iter()

object()

pow(x,y)  # 求次方,返回x**y的结果

pow(x,y,z) # 返回 x**y%z 的结果

property()  # 获取对象的所有属性

range()  # 获取随机数或随机字符 eg. range(10) 从0到10的随机数

repr()  # 执行传入对象中的_repr_方法

reversed()  #对序列化类型数据反向排序,返回一个新的对象。注意与对象的reverse方法区别,后者是就地改变对象

sorted() # 对序列化类型数据正向排序,返回一个新的对象。注意与对象的sort方法区别,后者是就地改变对象

slice()  #对序列化类型数据切片,返回一个新的对象。eg. slice(起始下标,终止下标,步长),步长默认为1

round()  # 返回四舍五入后的结果

int() #转换为整型

list() # 转换为列表类型

set()  # 转换为集合类型

str() #转换为字符串类型

tuple() # 转换为元组类型

type() # 返回对象类型

staticmethod() # 返回静态方法

super()  # 返回基类

vars() #返回当前模块中的所有变量

zip() # 接收多个序列化类型的数据,对各序列化数据中的元素,按索引位置分类成一个个元组。

eg. myList = list(zip([1,2,3],['a','b','c'])) 创建myList列表[(1,'a'),(2,'b'),(3,'c')]

mydic = dict(zip([1,2,3],['a','b','c'])) 创建mydic字典{1:'a',2:'b',3:'c'}

l1 = [1,2,3]

l2 = ['one','two','three']

list(zip(l1,l2))  返回[(1,'one'),(2,'two'),'(3,'three')]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值