Python菜鸟编程第六课之函数

Python菜鸟编程第六课之函数

1.引子

函数是对程序逻辑进行结构化或者过程化的一种编程方法

demo:

#给出两个数,求第一个数到第二个数之间的总和
def sumc(num1, num2):
    sum = 0
    while num1 <= num2:
        sum = sum + num1
        num1 += 1
    return sum
print(sumc(1, 4))
print(sumc(1, 15))
print(sumc(23, 36))
print(sumc(55, 68))
运行结果:
10
120
413
861

2.函数的使用

语法:

def function_name(arg1,arg2,..):
    '''statements'''#这里一般存放函数解释
    function_statements
    return value

2.1函数文档说明

使用function.__doc__来查看函数的说明文档

demo:

def add(x,y):
    '''求和'''
    return x+y
print(add.__doc__)
运行结果:
求和

2.2函数参数

函数中,参数的定义顺序必须是位置参数、默认参数、可变参数、命名关键词参数和关键词参数

函数参数种类:

  • 形参:只有在调用时才分配内存单元,调用结束后释放所分配的内存单元,因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。
  • 实参:实参是一个确定的值,能够传输给形参。
def info(name,age):
    info={"name" :name,"age":age}
    return info
print(info('city',1823))
print(info('小刘',18))
运行结果:
{'name': 'city', 'age': 1823}
{'name': '小刘', 'age': 18}

demo2:

print('1'.center(10, '*'))
test(1, 2)
print('2'.center(10, '*'))
test(x=1, y=2)
print('3'.center(10, '*'))
test(y=2, x=1)
print('4'.center(10, '*'))
test(1, y=2)
print('1'.center(10, '*'))

test(y=2, 1)#参数位置错误,结果报错

运行结果:
****1*****
1
2
****2*****
1
2
****3*****
1
2
****4*****
1
2
****1*****

    File "D:/PyCharm/BClass/PXClass/2019-7-23/daylistudy.py", line 95
    test(y=2, 1)
             ^
SyntaxError: positional argument follows keyword argument
2.21位置参数

demo:

#位置参数
def user_manage(name, age, job, hobby):
    print('用户管理系统'.center(16, '-'))
    print('\t:Name\t', name)
    print('\t:Age\t', age)
    print('\t:Job\t', job)
    print('\t:Hobby\t', hobby)
user_manage('Tom', 20, 'IT', 'Eat')
运行结果:
-----用户管理系统-----
	:Name	 Tom
	:Age	 20
	:Job	 IT
	:Hobby	 Eat
2.22默认值参数

函数中给予了参数默认值,假如调用函数时传参,会使用传递的参数,假如不传参,则使用默认值参数。

demo:

#默认值参数
def user_manage(name, age, job, hobby='Trip'):
    print('用户管理系统'.center(16, '-'))
    print('\t:Name\t', name)
    print('\t:Age\t', age)
    print('\t:Job\t', job)
    print('\t:Hobby\t', hobby)
user_manage('Tom', 20, 'IT', 'Eat')
user_manage('Tom', 20, 'IT', )
运行结果:
-----用户管理系统-----
	:Name	 Tom
	:Age	 20
	:Job	 IT
	:Hobby	 Eat
-----用户管理系统-----
	:Name	 Tom
	:Age	 20
	:Job	 IT
	:Hobby	 Trip
2.3关键词参数:

用于函数调用,通过“键-值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。

默认值参数,关键词参数,必须放在位置参数之后

demo:

def print_hello(name, sex):
    sex_dict = {1: u'先生', 2: u'女士'}
    print ('hello %s %s, welcome to python world!' %(name, sex_dict.get(sex, u'先生')))
# 以下是用关键字参数正确调用函数的实例
print_hello('tanggu', sex=1)
print_hello(name='tanggu', sex=1)
print_hello(sex=1, name='tanggu')

# 以下是错误的调用方式
print_hello(1, name='tanggu')#print_hello()为参数“name”获取多个值.
print_hello(name='tanggu',1)#参数位置放错
print_hello(sex=1, 'tanggu')#参数位置放错
2.4不定参数

在python中,不定参数主要是指*args和**kwargs。

它两主要用于函数定义,

*args 用来接收任意非键值对的任意数量的参数列表给函数,返回元组类型。

**kwargs 用来接收任意不定长的键值对列表给函数,返回字典类型。

demo1:

def uncertain_para(para, *args):
    print('普通位置参数:', para)
    print('不定参数:', args)
    print(type(args))
uncertain_para(1,2,3,4,'a','b')
uncertain_para([1,2,3],'ab','dc')
普通位置参数: 1
不定参数: (2, 3, 4, 'a', 'b')
<class 'tuple'>
普通位置参数: [1, 2, 3]
不定参数: ('ab', 'dc')
<class 'tuple'>运行结果:

demo2:

def avg(*a):
    sum = 0
    for i in a:
        sum += i
    return sum / len(a)
print(avg(5, 5, 5))
print(avg(3, 4, 5))
运行结果:
5.0
4.0

demo3:

def un_para_key(**kwargs):
    print(kwargs)
    print(type(kwargs))

un_para_key(a=1,b=2,c=3)
运行结果:
{'a': 1, 'b': 2, 'c': 3}
<class 'dict'>

demo4:

def un_para_key(aa,bb,*cc,**kwargs):
    print(aa)
    print(bb)
    print(cc)
    print(kwargs)
    print(type(kwargs))

un_para_key(1,2,3,4,5,6,'a','b',a=1,b=2,c=3)
运行结果:
1
2
(3, 4, 5, 6, 'a', 'b')
{'a': 1, 'b': 2, 'c': 3}
<class 'dict'>

练习题

写一个函数,计算传输字符中的数字,字母,空格以及其他字符的个数。

def strcount(str):
    nsum = 0
    asum = 0
    ksum = 0
    osum = 0
    for i in str:
        if i.isdigit():
            nsum += 1
        elif i.isalpha():
            asum += 1
        elif i == ' ':
            ksum += 1
        else:
            osum += 1
    print('字符串中数字的数量为:',nsum)
    print('字符串中字母的数量为:', asum)
    print('字符串中空格的数量为:', ksum)
    print('字符串中其他字符的数量为:', osum)
strcount(str1)
运行结果:
请输入一串字符串qqww,,,   123456
字符串中数字的数量为: 6
字符串中字母的数量为: 4
字符串中空格的数量为: 3
字符串中其他字符的数量为: 3

2.3函数属性

demo1:

def bar():
    print('in bar')

def foo():
    print('in foo')
    bar()
foo()
运行结果:
in foo
in bar

demo2:

新建一个py文件,名字命名为daylistudy.py.通过cmd运行此文件。

#daylistudy.py
def foo():
    '''foo()---properly creat string'''

def bar():
    pass

bar.__doc__='Oops,forget the doc str above'
bar.version=1.0

#控制台输入:
D:\PyCharm\BClass\PXClass\2019-7-23>python -i daylistudy.py
>>> dir()
['__annotations__', '__builtins__', '__cached__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'bar', 'foo']
>>> help(foo)
Help on function foo in module __main__:

foo()
    foo()---properly creat string
>>> bar.__doc__
'Oops,forget the doc str above'
>>> bar.version
1.0
>>>

2.4内嵌函数

demo:

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

foo()
#调用bar()
bar()
运行结果:
foo() called.
bar() called.
#调用bar()。bar()整个函数都处于外部foo()函数的作用域里(fool()是我们可以从外部访问的一个对象区域)。除了在fool()内部,其他地方无法对bar()进行调用。
Traceback (most recent call last):
  File "D:/PyCharm/BClass/PXClass/2019-7-23/daylistudy.py", line 210, in <module>
    bar()
NameError: name 'bar' is not defined

2.5变量作用域

作用域的产生:就作用域而言,python 和C语言有很大的差别,只有当变量在module,class,函数中定义的时候,才会有作用域 的概念。

demo:

def foo():
    a='foo'
    print(a)
foo()
print(a)
运行结果:
foo
Traceback (most recent call last):
  File "D:/PyCharm/BClass/PXClass/2019-7-23/daylistudy.py", line 216, in <module>
    print(a)
NameError: name 'a' is not defined

在作用域中定义的变量,一般只在作用域内有效。需要注意的是,在if–elif–else,for–else,while–else,try–except(else–finally)等关键词的语句块中不会产生作用域。

demo:

if True:
    a=100
print(a)
运行结果:
100

作用域的类型:Python中,使用一个变量时并不需要预先声明。但在真正使用的时候,他必须绑定在某个内存对象(被定义,赋值)。这种变量的绑定将在当前作用域中引入新的变量,同时,屏蔽外层作用域中的同名变量。

  • 局部作用域(locale—L)

    局部变量:包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。Python中也有递归,即自己调用自己,每次调用都会创建一个新的局部命名空间。在函数内部的变量声明,除非特别的声明为全局变量,否则均默认为局部变量。有些情况需要在函数内部定义全局变量,这时可以使用global关键字来声明变量的作用域为全局。局部变量域就像一个 栈,仅仅是暂时的存在,依赖创建该局部作用域的函数是否处于活动的状态。所以,一般建议尽量少定义全局变量,因为全局变量在模块文件运行的过程中会一直存在,占用内存空间。
    注意:如果需要在函数内部对全局变量赋值,需要在函数内部通过global语句声明该变量为全局变量。

  • 嵌套作用域(enclosing—E)

    E也包含在def关键字中,E和L是相对的,E相对于跟上层的函数而言也是L.与L的区别就在于:对于一个函数而言,L是定义在定义此函数内部的局部作用域。主要为了实现Python的闭包,而增加的实现。

  • 全局作用域(Global—G)

    即在模块层次中定义的变量。模块顶层申明的变量具有全局作用域,从外部来看,模块的全局变量就是一个模块对象的属性。

  • 内置作用域(built—B)

    系统固定模块中定义的变量。

搜索变量名的优先级:

​ 局部作用域>嵌套作用域>全局作用域>内置作用域

2.6全局变量和局部变量

demo:

gbl_str = 100#全局变量
def foo():
    loc_str = 200#局部变量
    return gbl_str + loc_str
print(foo())
print(gbl_str)
print(loc_str)
运行结果:
300
100
Traceback (most recent call last):
  File "D:/PyCharm/BClass/PXClass/2019-7-23/daylistudy.py", line 230, in <module>
    print(loc_str)
NameError: name 'loc_str' is not defined

demo1:

a=6688
def foo():
    a=666
    print('foo(),修改前:\t',a)
    a = 688
    print('foo(),修改后:\t', a)
foo()
运行结果:
foo(),修改前:	 666
foo(),修改后:	 688

demo2:

a=6688
def foo():
    # a=666
    print('foo(),修改前:\t',a)
    a = 688
    print('foo(),修改后:\t', a)
foo()
运行结果:
Traceback (most recent call last):
  File "D:/PyCharm/BClass/PXClass/2019-7-23/daylistudy.py", line 237, in <module>
    foo()
  File "D:/PyCharm/BClass/PXClass/2019-7-23/daylistudy.py", line 234, in foo
    print('foo(),修改前:\t',a)
UnboundLocalError: local variable 'a' referenced before assignment

demo1与demo2的运行差异,原因是在demo2中,foo()函数里搜索变量的优先级是局部作用域>全局作用域,当局部变量a与全局变量a重名,又由于优先级的存在,所以会报错。

demo3:

#将demo2中的变量a的变量名改为b
a=6688
def foo():
    # a=666
    print('foo(),修改前:\t',a)
    b = 688
    print('foo(),修改后:\t', a)
foo()
运行结果:
foo(),修改前:	 6688
foo(),修改后:	 6688

博主QQ:1031748759,欢迎批评指正!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值