当前位置: 澳门新濠3559 > 编程 > 正文

这被叫做用户自定义函数,定义函数test0

时间:2019-11-08 04:40来源:编程
函数的作用 函数可以让编程逻辑结构化以及模块化 无论是C、C++,Java还是Python,函数是必不可少的知识点,也是很重要的知识点,函数是完成一个功能的代码块,使用函数可以使逻辑结

函数的作用

函数可以让编程逻辑结构化以及模块化

无论是C、C++,Java还是Python,函数是必不可少的知识点,也是很重要的知识点,函数是完成一个功能的代码块,使用函数可以使逻辑结构变得更加清晰以及程序模块化设计

先来看看Python函数相关知识

 1 def test(x):
 2     """我是用来描述这个函数的"""
 3     x += 1
 4     return x
 5 
 6 # def : 定义函数的关键字
 7 # test: 函数名
 8 # (): 里面定义形参
 9 # """ """: 用来描述这个函数的功能以及所传函数,返回值,
10 # x+= 1: 函数执行的代码块
11 # return :定义返回值

函数的的运行:函数名()  只有加上这个括号才是运行这个函数

1.函数名的命名规则

  • 函数名必须以下划线或字母开头,可以包含任意字母、数字或下划线的组合。不能使用任何的标点符号;
  • 函数名是区分大小写的。
  • 函数名不能是保留字。

一、函数的介绍

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数

函数的好处:

  • 代码重用
  • 保持一致,易于维护
  • 可扩展性

Python--function,python

函数就是"变量".定义一个函数就是相当于将一个函数体赋值给函数名.

一、参数的调用

def test0(x,y,z):            #定义函数test0,形参x,y,z
  print("x=%d,y=%d,z=%d" %(x,y,z))  #依次输出形参的值
test0(1,2,3)              #位置参数调用
test0(x=2,z=0,y=1)           #关键字调用
test0(2,z=1,y=3)            #位置参数与关键字调用,位置参数要在前


x=1,y=2,z=3
x=2,y=1,z=0

函数运行的结束

  当函数执行遇到return,后面所有的代码都是无效的,都不会执行

def test():
    print('我会打印')
    return
    print('我不会被打印')
test()
"""
我会打印
"""

函数参数:

  1. 形参:只在函数内部有效
  2. 实参:
  3. 位置参数和关键字参数
  4. 默认参数
  5. 参数组

    author = "Tang"

    # 形参:x y z def test(x,y,z):

    print(x)
    print(y)
    print(z)
    

    test(1,2,3) # 实参:1,2,3

    # 位置参数 一一对应 def test(x,y,z):

    print(x)
    print(y)
    print(z)
    

    test(1,2,3) # # test(1,2) # 缺一不可 报错 # test(1,2,3,4) # 多一不可 报错

    # 关键字参数 def test(x,y,z):

    print(x) # 2
    print(y) # 1
    print(z) # 3
    

    test(y=1,x=2,z=3)

    # 位置参数 & 关键字参数 混搭 # 位置参数一定要在关键字的左边 def test(x,y,z):

    print(x) # 2
    print(y) # 1
    print(z) # 3
    

    # test(1,3,y=2) # 报错 位置参数必须一一对应 test(1,y=3,z=2) # test(1,3,z=2,y=3) # 报错,传入参数比形参多 没有覆盖一说

    # x,z 为默认参数 def test(x,y=1,z=3):

    print(x,y,z)
    

    澳门新濠3559,test(10) # 10 1 3默认参数不传 使用默认的 test(10,20,30) # 10 20 30 如果传了就覆盖

# 不定参数
# 参数组: * 列表 元组, **字典 键值对
# 第一种
def test(x,*args):
    print(x) # 1
    print(args) # (2, 3, 4, 5)
    print(*args) # 2 3 4 5 注意:这里没有换行
test(1,2,3,4,5)

# 第二种 *()
def test(x,*args):
    print(x) # 1
    print(args) # ((2, 3, 4, 5, 6)
    print(*args) # 2 3 4 5 6 注意:这里没有换行
test(1,2,3,*(4,5,6))

# 第三种 ()
def test(x,*args):
    print(x) # 1
    print(args) # ((2, 3, (4, 5, 6))
    print(*args) # 2 3 (4, 5, 6) 注意:这里没有换行
test(1,2,3,(4,5,6))

# 第四种 []
def test(x,*args):
    print(x) # 1
    print(args) # (2, 3, [4, 5, 6])
    print(*args) # 2 3 [4, 5, 6] 注意:这里没有换行
test(1,2,3,[4,5,6])

# 第五种 *[]
def test(x,*args):
    print(x) # 1
    print(args) # ((2, 3, 4, 5, 6)
    print(*args) # 2 3 4 5 6 注意:这里没有换行
test(1,2,3,*[4,5,6])

# **kwargs 字典 键值对
# 第一种
def test(x,**kwargs):
    print(x) # 1
    print(kwargs) # {'y': 2, 'z': 3}
    # print(**kwargs) # 报错
test(1,y=2,z=3)

# 第二种
def test(x,**kwargs):
    print(x) # 1
    print(kwargs) # {'y': 2, 'z': 3}
    # print(**kwargs) # 报错
# test(1,{"y":2,"z":3}) # 报错
test(1,**{"y":2,"z":3})

2. 形参和实参

形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)

实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参   

区别:形参是虚拟的,不占用内存空间,.形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参

二、函数的定义

函数的定义规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 这被叫做用户自定义函数,定义函数test0。()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明
  • 函数内容以冒号起始,并且缩进
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None

函数的语法:

  

def 函数名:
    函数体

  

函数的示例:

def print_hello():
    """
    打印hello
    :return: 
    """
    print("hello")

  

x=2,y=3,z=1

def test1(x,y=2):           #定义默认参数,可省略传递
  print("x=%d,y=%d" %(x,y))

函数里面可以调用函数

__author__ = "Tang"

def test1():
    print('我是test1')
def test2():
    print('我是test2')
    test1()
test2()

"""
我是test2
我是test1
"""

3.参数

关键字参数:使用参数名提供参数叫做关键字参数。它的主要作用在于可以明确每个参数的作用。关键字参数最厉害的地方在于可以在函数中给参数提供默认值。

下面例子的必须参数也叫位置参数,因为它们的位置比它们的名字还要重要。

参数前的星号将所有值放置在同一个元组中。可以说是将这些值收集起来,然后使用。

两个星号能处理关键字参数的收集操作。

#必须参数
def f(name,age):
    print("My name is: %s and my age is: %d"%(name,age))
f('greg',18)

#关键字参数
#f(16,'greg')报错
f(age=16,name='greg')

#默认参数
def print_info(name, age, sex='male'):
    print('Name:%s' % name)
    print('age:%s' % age)
    print('Sex:%s' % sex)
    return
print_info('Greg', 18)
print_info('Wirt', 40, 'female')

#不定长参数
def add(*args):#加法器
    print(args)
    sum=0
    for i in args:
        sum+=i
    print(sum)
add(1,2,3,4,5)

#加了星号(*)的变量名会存放所有未命名的变量参数。而加(**)的变量名会存放命名的变量参数
def p(*args,**kwargs):
    print(args)
    print(kwargs)
    for i in kwargs:
        print('%s:%s' % (i, kwargs[i]))  # 根据参数可以打印任意相关信息了
p('greg',18,'male',job='IT',hobby="girls")

参数使用

def a(*args):
    print(args)

a(*[1, 2, 5])

def b(**kargs):
    print(kargs)

b(**{'name': 'alex'})


def c(x, y, d):
    return d(x) + d(y)
res = c(3, -6, abs)
print(res)

def foo():
    x=3
    def bar():
        return x
    return bar

def func(name, *args, **kwargs):  # def print_info(name,**kwargs,*args):报错
    print('Name:%s' % name)
    print('args:', args)
    print('kwargs:', kwargs)
    return
func('greg', 18, hobby='girl', nationality='Chinese', ability='Python')

三、函数的返回值

根据示例来看下python的返回值:

def fun2():
    msg = "hello world"
    return msg


def fun3():
    return 1, 2 ,3 

aa = fun1()
bb = fun2()
cc = fun3()
print(aa)
print(bb)
print(cc)

# 输出结果:
# None
# hello world
# (1, 2, 3)

总结:

  1.函数中如果没有return语句返回,那么python函数会默认返回None

  2.函数返回值数为0,函数默认返回None;函数返回值数为1是,则返回object;返回值数大于1时,则返回的是一个tuple;

 

test1(1)

全局变量与局部变量

  1. 全局变量一般都是大写 ,在整个程序中都可以被访问
  2. 局部变量,定义在代码块中,for循环,函数等

    author = "Tang"

    name = "我是全局变量" # def test():

    name = "我是局部变量"
    print(name) # 我是局部变量
    

    test() print(name) # 我是全局变量

以上例子可以看到,当局部变量和全局变量都为同一个变量名的时候,在代码块里面,首先先找代码块中的变量也就是局部变量,当代码块中找不到该变量,就找全局变量

name = "我是全局变量" #
def test():
    print(name) # 我是全局变量
test()
print(name) # 我是全局变量

在代码块中修改全局变量需要用到关键字 global

name = "我是全局变量" #
def test():
    global name
    name = "我是全局变量,我被修改啦"
    print(name) # 我是全局变量,我被修改啦
test()
print(name) # 我是全局变量,我被修改啦

请注意看我哦!

name = "我是全局变量" 
def test():
    global name
    print(name) # 我是全局变量
    name = "我是全局变量,我被修改啦"
    print(name) # 我是全局变量,我被修改啦
test()
print(name) # 我是全局变量,我被修改啦

总结:当找不到代码块中的变量,就会到上一级中找该变量。当看到global 关键字,就要想到要重修赋值全局变量。如果没有global关键字,只能读取全局变量,无法重新赋值全局变量的值。

四 函数的返回值

要想获取函数的执行结果,就可以用return语句把结果返回

注意:

  1. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,也可以理解为 return 语句代表着函数的结束
  2. 如果未在函数中指定return,那这个函数的返回值为None  
  3. return多个对象,解释器会把这多个对象组装成一个元组作为一个一个整体结果输出。

四、函数的参数

 函数参数的原则:

  • 形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
  • 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
  • 位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)
  • 默认参数
  • 参数组

x=1,y=2

def test2(*args):     #不固定形参,可传递多个,把关键字参数转换成元组tuple
  print(args)
test2(1,2,3)

下面请注意

当全局变量为可变数据类型的时候,可在代码块中对全局变量进行修改(增,删,改),但是不能对全局变量进行重新赋值,赋值的只是局部变量,除非用global 关键字进行声明为全局变量,此时才是赋值给全局变量

# 第六种 列表添加
NAME = ["tang","lao"]
def test():
    NAME.append('er')
    print(NAME) # ['tang', 'lao', 'er']
test()
print(NAME) # ['tang', 'lao', 'er']

# 第七种 列表删除
NAME = ["tang","lao",'er']
def test():
    NAME.remove('er')
    print(NAME) # ['tang', 'lao']
test()
print(NAME) # ['tang', 'lao']

# 第八种 列表修改
NAME = ["tang","lao",'er']
def test():
    NAME[0] = "chen"
    print(NAME) # ['chen', 'lao', 'er']
test()
print(NAME) # ['chen', 'lao', 'er']

# 第九种 字典 修改
NAME = {"name":"tang","age":18}
def test():
    NAME["name"] = "chen"
    print(NAME) # {'name': 'chen', 'age': 18}
test()
print(NAME) # {'name': 'chen', 'age': 18}

# 第九种 字典 添加
NAME = {"name":"tang","age":18}
def test():
    NAME["hobby"] = "girl"
    print(NAME) # {'name': 'tang', 'age': 18, 'hobby': 'girl'}
test()
print(NAME) # {'name': 'tang', 'age': 18, 'hobby': 'girl'}

# 第九种 字典 删除
NAME = {"name":"tang","age":18}
def test():
    del NAME["name"]
    print(NAME) # {'age': 18}
test()
print(NAME) # {'age': 18}

# 没有global 赋值
NAME = {"name":"tang","age":18}
def test():
    NAME = {'a':1,'b':2}
    print(NAME) # {'a': 1, 'b': 2}
test()
print(NAME) # {'name': 'tang', 'age': 18}

# 有global 赋值
NAME = {"name":"tang","age":18}
def test():
    global NAME
    NAME = {'a':1,'b':2}
    print(NAME) # {'a': 1, 'b': 2}
test()
print(NAME) # {'a': 1, 'b': 2}

五 作用域

普通参数

def fun1(name):   # name为形式参数
    print(name)


aa = "hello"
fun1(aa)  # aa为实参

  

test2(*[1,2,3])

(1, 2, 3)

 一个错误的特例

__author__ = "Tang"

# 错误的例子     报错
# NAME = ['tang','lao','er']
# def test():
#     NAME = "chen"
#     global NAME
#     print(NAME)
# test()
# print(NAME)

# 改正
NAME = "tang"
def test():
    global NAME # 我是声明 我要在 NAME 其他操作的前面
    NAME = "chen"
    print(NAME) # chen
test()
print(NAME) # chen

总结:声明要在其他操作的前面,不然会报错。。。。。。

 

为了防止错误,全局变量大写,局部变量小写,可以防止编程出现没必要的错误

作用域介绍 

python中的作用域分4种情况:

  • L:local,局部作用域,即函数中定义的变量;
  • E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
  • G:globa,全局变量,就是模块级别定义的变量;
  • B:built-in,系统固定模块里面的变量,比如int, bytearray等。 搜索变量的优先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB。

    #__author: greg #date: 2017/9/6 9:02 x = int(2.9) # int built-in g_count = 0 # global def outer():

    o_count = 1  # enclosing
    def inner():
        i_count = 2  # local
        print(o_count) #1
    # print(i_count) 找不到
    inner()
    

    outer() # print(o_count) #找不到

当然,local和enclosing是相对的,enclosing变量相对上层来说也是local。

块级作用域:

# 块级作用域
if 1 == 1:
    name = "greg"
print(name) #greg

for i in range(10):
    age = i
print(age) #9

代码执行成功,没有问题;在Java/C#中,执行上面的代码会提示name,age没有定义,而在Python中可以执行成功,这是因为在Python中是没有块级作用域的,代码块里的变量,外部可以调用,所以可运行成功;

默认参数

def func(name, age=18):
    print("%s:%s" % (name, age))


# 指定参数
func('wupeiqi', 19)  # 使用默认参数
func('alex')
# 注:默认参数需要放在参数列表最后

 

(1, 2, 3)

def test3(**kwargs):     #将字典作为形参,可传递多个,传递的值为key:value
  print(kwargs)
  print(kwargs['name'])
  print(kwargs['age'])
  print(kwargs['sex'])
test3(name='xy',age=23,sex="N")

函数嵌套

 1 __author__ = "Tang"
 2 
 3 # 函数嵌套
 4 NAME = "全局"
 5 def yeye():
 6     name = "爷爷级别"
 7     print(name)
 8     def fu():
 9         name =  "父级别"
10         print(name)
11         def zi():
12             name = "子级别"
13             print(name)
14             def sunzi():
15                 name = "孙子级别"
16                 print(name)
17             sunzi()
18         zi()
19     fu()
20 yeye()
21 print(NAME)
22 
23 """
24 爷爷级别
25 父级别
26 子级别
27 孙子级别
28 全局
29 """

再来一个,请仔细看

name = "A"

def test():
    name = "B"
    def test_test():
        global name
        name = "C"
    test_test()
    print(name) # B
print(name) #  A
test()
print(name) # C

作用域产生 

>>> x=1
>>> scope=vars()
>>> scope['x']
1
>>> scope['x']+=1
>>> x
2

在执行x=1后,名称x引用到值1.这就像用字典一样,键引用值,当然,变量和所对应的值用的是这个不可见的字典,实际上这么说已经很接近真实情况了,内建的vars函数可以返回这个字典。这类不可见字典叫做命名空间或者作用域。除了全局作用于外,每个函数调用都会创建一个新的作用域:函数内的变量被称为局部变量。

全局变量可以使用globals函数获取全局变量值,该函数的近亲是vars,它可以返回全局变量的字典(locals返回局部变量的字典)

>>> def combine(parameter):
...     print(parameter+globals()['parameter'])
...
>>> parameter='berry'
>>> combine('melon')
melonberry

首先看函数的嵌套:

>>> def foo():
...     def bar():
...         print("Hello,world")
...     bar()
...
>>> foo()
Hello,world

嵌套作用域:

>>> def multiplier(factor):
...     def multiplyByFactor(number):
...         return number*factor
...     return multiplyByFactor
...
>>> double=multiplier(x)
>>> double(5)
5
>>> triple=multiplier(3)
>>> triple(3)
9
>>> multiplier(5)(4)
20

类似multiplyByFactor函数存储子封闭作用域的行为叫闭包closure。

外部作用域的变量一般来说是不能进行重新绑定的。nonlocal关键字被引入。它和global关键字的使用方式类似,可以让用户对外部作用域(但并非全局作用域)的变量进行赋值。

>>> def foo():x=12
...
>>> x=1
>>> foo()
>>> x
1

这里的foo函数改变了变量x,但在最后,x并没有改变。因为调用foo,新的命名空间就被创建了,它作用于foo内的代码块。

在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if、try、for等)是不会引入新的作用域的,如下代码:

if 2>1:
    x = 1
print(x)  # 1

这个是没有问题的,if并没有引入一个新的作用域,x仍处在当前作用域中,后面代码可以使用。

def test():
    x = 2
print(x) # NameError: name 'x2' is not defined

def、class、lambda是可以引入新作用域的。

>>> x=6
>>> def f():
...     print(x)
...     x=5
...
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment

>>> def f2():
... x=5
... print(x)
...
>>> f2()
5

错误的原因在于print(x)时,解释器会在局部作用域找,会找到x=5(函数已经加载到内存),但x使用在声明前了,所以报错

动态参数

def func1(*args):
    print(args)

# 执行方式一
func1(11, 33, 4, 4454, 5)
# 执行方式二
li = [11, 2, 2, 3, 3, 4, 54]
func1(*li)


def func2(**kwargs):
    print(kwargs)
# 执行方式一
func2(name='wupeiqi', age=18)
# 执行方式二
dict1 = {'name': 'fyh', "age": 18, 'gender': 'male'}
func2(**dict1)

 

test3(**{'name':'xy','age':23,'sex':'N'})

{'name': 'xy', 'age': 23, 'sex': 'N'}
xy
23
N
{'name': 'xy', 'age': 23, 'sex': 'N'}
xy
23

关键字 nonlocal 声明上一级的变量

name = "A"

def test():
    name = "B"
    def test_test():
        nonlocal name # nonlocal,指定上一级变量
        name = "C"
    test_test()
    print(name) # C
print(name) #  A
test()
print(name) # A

nonlocal 只能使用于两级或多级函数嵌套,一级嵌套会导致程序报错,下面请看一个错误的示例

name = "A"
def test():
    nonlocal name # 报错
    name = "C"
    print(name)
print(name)
test()
print(name)

 global关键字 

当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了,当修改的变量是在全局作用域(global作用域)上的,就要使用global先声明一下,

万能参数

# 万能参数
def func(*args, **kwargs):
    pass

 

N

def test4(name,**kwargs):          #位置参数和字典参数传递值
  print(name,kwargs)

函数声明与调用的顺序

函数即变量,调用函数前需先声明

# 第一种情况
def foo():
    print("foo")
    bar()

def bar():
    print("bar")
foo()

下面看一个错误的例子

# 第二种情况 报错的例子
def foo():
    print("foo")
    bar()

foo()
def bar():
    print("bar")

nonlocal关键字 

global关键字声明的变量必须在全局作用域上,不能嵌套作用域上,当要修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量怎么办呢,这时就需要nonlocal关键字了

代码如下:

count = 10
def outer():
    global count
    print(count)    #10
    count = 100
    print(count)    #100
outer()
print(count)        #100

#nonlocal
def outer2():
    count = 10
    def inner():
        nonlocal count
        count = 20
        print(count) #20
    inner()
    print(count)     #20
outer2()

总结一下

(1)变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局>python内置作用域;

(2)只有模块、类、及函数才能引入新作用域;

(3)对于一个变量,内部作用域先声明就会覆盖外部变量,不声明直接使用,就会使用外部作用域的变量;

(4)内部作用域要修改外部作用域变量的值时,全局变量要使用global关键字,嵌套作用域变量要使用nonlocal关键字。nonlocal是python3新增的关键字,有了这个 关键字,就能完美的实现闭包了。 

作用域链

name = "greg"
def f1():
    name = "Eric"
    def f2():
        name = "Snor"
        print(name)
    f2()
f1() #Snor

Python中有作用域链,变量会由内到外找,先去自己作用域去找,自己没有再去上级去找,直到找不到报错

name = "greg"
# def f1():
#     print(name)
# def f2():
#     name = "eric"
#     f1()
# f2()#greg

def f1():
    print(name)
def f2():
    name = "eric"
    return f1
ret = f2()
ret() #greg

f2()执行结果为函数f1的内存地址,即ret=f1;执行ret()等同于执行f1(),执行f1()时与f2()没有任何关系,name = "greg"与f1()在一个作用域链,函数内部没有变量是会向外找,所以此时变量name值为greg

五、全局变量与局部变量

全局变量与局部变量的本质在于作用域的不同

全局变量说白了就是在整个py文件中声明,全局范围内都可以使用

局部变量是在某个函数内声明的,只能在函数内部使用

 

举例:

def fun1():
    name = "aa"

print(name)

 

执行结果:

  澳门新濠3559 1

报错的原因:试图访问局部变量而报的错

 

test4('xy',age=23,sex='N')

 函数递归

  1.  必须有一个明确的结束条件(if 判断)return结束
  2. 每次进入更深一层递归时,问题规模相比上一次递归都应有所减少

 

 1 __author__ = "Tang"
 2 
 3 def calc(n):
 4     print(n)
 5     if int(n / 2) ==0:
 6         return n
 7     res = calc(int(n/2))
 8     print("****",res)
 9     return res
10 n = calc(10)
11 print(n)
12 """
13 10
14 5
15 2
16 1
17 **** 1
18 **** 1
19 **** 1
20 1
21 """

 

递归代码练习:一个快速排序的例子

 1 # coding:utf-8
 2 def quick_sort(alist, first, last):
 3     """快速排序"""
 4     if first >= last:
 5         return
 6     mid_value = alist[first]
 7     low = first
 8     high = last
 9     while low < high:
10         # high 左移
11         while low < high and alist[high] >= mid_value:
12             high -= 1
13         alist[low] = alist[high]
14 
15         while low < high and alist[low] < mid_value:
16             low += 1
17         alist[high] = alist[low]
18     # 循环退出时,满足条件low==high
19     alist[low] = mid_value
20 
21     # 对low左边的列表执行快速排序
22     quick_sort(alist, first, low-1)
23 
24     # 对low右边的列表排序
25     quick_sort(alist, low+1, last)
26 
27 
28 if __name__ == "__main__":
29     li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
30     print(li)
31     quick_sort(li, 0, len(li)-1)
32     print(li)

斐波那契数列

__author__ = "Tang"

# 斐波那契数列
a = 0
b = 1
while b < 1000:
    print(b,end=" ")
    a,b = b, a+b
# 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

# 生成前20项
lis =[]
for i in range(20):
    if i ==0 or i ==1:# 第1,2项 都为1
        lis.append(1)
    else:
        lis.append(lis[i-2]+lis[i-1])# 从第3项开始每项值为前两项值之和
print(lis) # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

# 递归实现
li = []
def test(a, b):
    if a > 1000 or b > 1000:
        return
    li.append(a)
    li.append(b)
    a = a + b
    b = a + b
    test(a, b)
test(1, 1)
print(li) # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]

 函数作用域相关练习

 1 __author__ = "Tang"
 2 
 3 """函数的作用域相关练习"""
 4 
 5 """
 6 寻找变量的顺序:当前函数里面寻找,如果找不到就往上一层函数找,实在找不到就找全局变量
 7 函数的调用:函数名+ () 函数名即变量,只要取得函数地址就可以
 8 """
 9 
10 # 第一种
11 def foo():
12     print("我是foo")
13     def bar():
14         print("我是bar")
15     bar()
16 foo()
17 # bar() # 报错 不可以直接调用 记住:要想执行里面的,就要先执行外面的,想象盒子里面包含盒子,外面的盒子不拿掉,里面的也拿不出来
18 """
19 我是foo
20 我是bar
21 """
22 
23 # 第二种
24 def foo():
25     print("我是foo")
26     def bar():
27         print("我是bar")
28     return bar
29 test = foo()
30 test() # 可以调用 test拿到bar函数的地址
31 """
32 我是foo
33 我是bar
34 """
35 
36 # 第三种
37 def test():
38     print("我是test")
39 print(test()) # 没有没有返回值 默认为None
40 """
41 我是test
42 None
43 """
44 
45 # 第四种
46 def test():
47     print("我是test")
48     return 10
49 print(test())
50 """
51 我是test
52 10
53 """
54 
55 # 第五种
56 name = "tang"
57 def foo():
58     name = "chen"
59     def bar():
60         name = "li"
61         print(name)
62     return bar
63 a = foo()
64 print(a)
65 a()
66 """
67 <function foo.<locals>.bar at 0x02FE0B28>
68 li
69 """
70 
71 # 第六种
72 name = "tang"
73 def foo():
74     name = "chen"
75     def bar():
76         print(name)
77     return bar
78 a = foo()
79 print(a)
80 a()
81 """
82 <function foo.<locals>.bar at 0x00830B70>
83 chen
84 """
85 
86 # 第七种
87 name = "tang"
88 def foo():
89     name = "chen"
90     def bar():
91         print(name)
92     return bar
93 foo()()
94 """
95 chen
96 """

六 内置函数

filter对于序列中的元素进行筛选,最终获取符合条件的序列

#filter(function,sequence))
str = ['a', 'b', 'c', 'd']
def fun1(s):
    if s != 'a':
        return s
ret = filter(fun1, str)
print(ret)
print(list(ret))  # ret是一个迭代器对象
"""
<filter object at 0x000002C45B43C780>
['b', 'c', 'd']
"""

map遍历序列,对序列中每个元素进行操作,最终获取新的序列。map(function, sequence) 

str = ['a', 'b', 'c', 'd']
def fun2(s):
    return s + "alvin"
ret = map(fun2, str)
print(ret)  # map object的迭代器
print(list(ret))  # ['aalvin', 'balvin', 'calvin', 'dalvin']

reduce对于序列内所有元素进行累计操作。reduce(function, sequence, starting_value)

from functools import reduce
def add1(x, y):
    return x + y
print(reduce(add1, range(1, 100)))  ## 4950 (注:1+2+...+99)
print(reduce(add1, range(1, 100), 20))  ## 4970 (注:1+2+...+99+20)

对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用.

lambda普通函数与匿名函数的对比

学习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即

result = 值1 if 条件 else 值2

如果条件为真:result = 值1
如果条件为假:result = 值2

对于简单的函数,也存在一种简便的表示方式,即:lambda表达式

# 普通函数
def add(a, b):
    return a + b
print(add(2, 3)) 
# 匿名函数
add = lambda a, b: a + b
print(add(2, 3))

面试题1:

counter = 1

def doLotsOfStuff():
    global counter
    for i in (1, 2, 3):
        counter += 1

doLotsOfStuff()
print(counter) 

答案是4 循环3次

面试题2:

>>> li = [lambda :x for x in range(10)]
>>> li
[<function <listcomp>.<lambda> at 0x000001B5AE9D4378>, <function <listcomp>.<lambda> at 0x000001B5AE9D4400>, <function <listcomp>.<lambda> at 0x000001B5AE9D4488>, <function <listcomp>.<lambda> at 0x000001B5AE9D4510>, <function <listcomp>.<lambda> at 0x000001B5AE9D47B8>, <function <listcomp>.<lambda> at 0x000001B5AE9D4840>, <function <listcomp>.<lambda> at 0x000001B5AE9D48C8>, <function <listcomp>.<lambda> at 0x000001B5AE9D4950>, <function <listcomp>.<lambda> at 0x000001B5AE9D49D8>, <function <listcomp>.<lambda> at 0x000001B5AE9D4A60>]
>>> print(type(li))
<class 'list'>
>>> print(type(li[0]))
<class 'function'>
>>> res = li[0]()
>>> print(res)

<class 'list'>
<class 'function'>
9

扩展:

tp=(lambda: x for x in range(10))
print(type(tp))#<class 'generator'>
print(next(tp))#<function <genexpr>.<lambda> at 0x0000020BC7973E18>
print(next(tp)())#1
print(next(tp)())#2
print(next(tp)())#3
print(next(tp)())#4

 

局部变量与全局变量变量名一样

  • 全局变量与局部变量名一致,函数内部会优先使用局部变量
  • 修改局部变量不会影响到全局变量

    name = "bb"

    def print_name():

    name = "aa"
    print(name)
    

    print_name()

    print(name)

    # 打印的结果为 # aa # bb

 

xy {'age': 23, 'sex': 'N'}

def test5(name,age=18,**kwargs):    #传递位置参数,关键字参数,字典参数
  print(name,age,kwargs)
test5('xy',sex='N',hobby='belle',age=23)

匿名函数 lambda

lambda x : x+1 一个简单的匿名函数

__author__ = "Tang"


def test(x):
    return x + 1
res = test(10)
print(res) # 11

#  匿名函数实现上面函数
func = lambda x:x+1
print(func(10)) # 11

下面通过一些简单的例子来加深匿名函数的理解

# 第一个
name = "tang"
def change_name(x):
    return x +"_sb"
res = change_name(name)
print(res) # tang_sb

res = lambda x:name+"_sb"
print(res(name)) # tang_sb
print(res("tang")) # tang_sb

res = lambda x:x+"_sb"
print(res(name)) # tang_sb
print(res("tang")) # tang_sb


# 第二个 传多个参数
func = lambda x,y,z:x+y+z
print(func(1,2,3)) # 6

# 第三个
name1 = "tang"
name2 = "lao"
name3 = "er"
x = lambda name1,name2,name3:"".join([name1,name2,name3])
print(x(name1,name2,name3)) # tanglaoer

 

global关键字

使用global关键字:则会告诉python编译器,这个变量是全局变量而不是全局变量,这样在函数体内修改变量会影响全局了

name = "bb"


def print_name():
    global name
    name = "aa"
    print(name)

print_name()
print(name)

# 打印的结果:
# aa
# aa

  

#匹配不到形参时,参数后移至**kwargs

nonlocal关键字

nonlocal关键字在python3中新出现的关键字,作用:用来在函数或其他作用域中使用外层(非全局)变量

nonlocal  适用于在局部函数 中 的局部函数, 把最内层的局部 变量设置成外层局部可用,但是还不是全局的。

注:nonlocal必须要绑定局部变量

def fun1():
    num = 1

    def fun2():
        nonlocal num    # 此处不能使用global,只能使用nonlocal
        num += 1
        return num
    return fun2

aa = fun1()

print(aa())

  

xy 23 {'sex': 'N', 'hobby': 'belle'}

def test6(name,age,*args,**kwargs):      #定义多个类型形参,tuple,字典
  print(name,age,args,kwargs)
test6('xy',23,'python','perl',linux='shell',sql='mariadb',sex='N')

六、匿名函数

lamba函数也叫匿名函数,即函数没有具体的名称

lambda语句中,冒号前是参数,可以有多个,用逗号隔开,冒号右边的返回值

def calc(x):
    return x + 1

# 用lambda进行改写如下:
calc2 = lambda x: x + 1
# 进行调用
print(calc2(10))

  

              #依次匹配形参,传递的位置形参要在关键字形参前面

xy 23 ('python', 'perl') {'linux': 'shell', 'sql': 'mariadb', 'sex':

七、初识高阶函数

'N'}

二、函数的返回值return

  函数中return表示函数结束

  Python中的函数的返回值可以是一个参数,也可以是多个参数以元组格式返回

def return_test():
    print("line one")
    print("line two")
    return 'hello',['nice','to','meet','you'],666 #返回多个参数
    print("line three")        #return后面不执行
print(return_test())          #打印函数返回值
-----------------------------------------------------------------------------

line one
line two
('hello', ['nice','to','meet','you'],666)    #返回值为元组tuple格式

=============================================================================

 三、匿名函数

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

函数没有名字,不必担心函数名冲突

calc = lambda x:x**3    #lambda表示匿名函数,冒号前面的x表示函数参数

print("calc is %s" %calc(3))


calc is 27

=============================================================================

四、函数内的局部变量与全局变量

name = 'xy'    #name为全局变量
def test7(name):            #函数内name为局部变量
  print("before change",name)
  name = "architect"        #函数内更改变量的值,函数外不会改变
  print("after change",name)    #函数内打印局部变量name的值
test7(name)

map函数

map处理序列中的每个元素,得到一个结果(迭代器),该迭代器元素个数与位置不变

list1 = [1, 2, 3, 4, 5]
list2 = map(lambda x: x+1, list1)  # map的第一个参数为函数,后面的参数为可迭代对象
print(list(list2))

# 结果:[2, 3, 4, 5, 6]

  

print(name)

before change xy
after change architect

filter函数

filter(过滤):遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来,组成新的迭代器

list1 = ["1111aaa", "2222aaa", "3333aaa", "4444", "5555", "6666"]
list2 = filter(lambda x: x.endswith("aaa"), list1)  # 有过滤的作用
print(list(list2))

# 运行结果:['1111aaa', '2222aaa', '3333aaa']

  

xy            #函数外的值

school = "ahxh edu"
def test8(name):            #全局变量不会被局部改变
  global school            #global,函数中申明全局变量,不建议更改
  school = 'xwxh edu'        #将全局变量重新赋值
  print(school)
test8(school)

reduce函数

reduce 处理一个序列,把序列进行合并操作

from functools import reduce

list1 = [1, 2, 3, 4, 5]
aa = reduce(lambda x, y: x+y, list1)  # 前一个参数的函数必须是两个参数
print(aa)

# 运行结果:15

  

print(school)

xwxh edu               #函数内的值

八、内置函数

澳门新濠3559 2

学习资料参考:

xwxh edu                #此处全局变量已被在函数中更改

names_list=['xy','jack','lucy']
def test9():      #当传递list,tuple,字典时传递的是地址,函数中可改变全局变量
  names_list[0] = 'architect'
  print("inside func",names_list)
test9()

print(names_list)

inside func ['architect', 'jack', 'lucy']        #函数内的值

['architect', 'jack', 'lucy']              #函数外的值

五、函数的递归
    递归约999次启动程序保护关闭进程,递归必须有明确的结束条件
    进入深一层次递归算法要减少,递归的效率不高,容易导致栈溢出
def calc(n):
  print(n)
  return calc(n+1)                  #无限递归

calc(0)

996
Traceback (most recent call last):
File "递归.py", line 8, in <module>
calc(0)
File "递归.py", line 7, in calc
return calc(n+1)
File "递归.py", line 7, in calc
return calc(n+1)
File "递归.py", line 7, in calc
return calc(n+1)
[Previous line repeated 992 more times]
File "递归.py", line 6, in calc
print(n)
RecursionError: maximum recursion depth exceeded while calling a Python

object

def calc(n):
  print(n)
  if int(n/2) ==0:
    return n
  return calc(int(n/2)) #递归调用函数

calc(10)

10
5
2

1

六、高阶函数

把一个函数名当做实参传递给另外一个函数

返回值中包含函数名 

def add(x,y,f):             #高阶函数,函数可以传递函数
  return f(x) + f(y)

res = add(3,-6,abs)           #abs为python内置函数,计算绝对值

print("res=%d" %(res))

res=9

=============================================================================

函数名指向函数体,将函数名传递给形参,形参共有函数体地址

 import time        #导入time模块

def high1():
  time.sleep(3)      #睡眠3秒
    print("this is high1")
def high2(func):
    start_time=time.time()    
    func()          #调用形参函数func(),实参是high1()
    stop_time=time.time()
    print("the func run time %s" %(stop_time-start_time)) #结束减开始时间,程序运行时间
high2(high1)

this is high1
the func run time 3.015038013458252

=============================================================================
Python内置函数

Built-in Functions
abs() dict() help() min() setattr()
all() dir() hex() next() slice()
any() divmod() id() object() sorted()
ascii() enumerate() input() oct() staticmethod()
bin() eval() int() open() str()
bool() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
getattr() locals() repr() zip() classmethod()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()
delattr() hash() memoryview() set()

 

函数就是"变量".定义一个函数就是相当于将一个函数体赋值给函数名. 一、参数的调用 def test0(x,y,z): #定义函数test0,形...

编辑:编程 本文来源:这被叫做用户自定义函数,定义函数test0

关键词: