Python函数篇
1.函数名的命名规则:
- 函数名必须以下划线或字母开头,可以包含任意字母、数字或下划线的组合。不能使用任何的标点符号;
- 函数名是区分大小写的。
- 函数名不能是保留字。
2. 形参和实参
形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)
实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参
区别:形参是虚拟的,不占用内存空间,.形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参
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')
四 函数的返回值
要想获取函数的执行结果,就可以用return语句把结果返回
注意:
- 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,也可以理解为 return 语句代表着函数的结束
- 如果未在函数中指定return,那这个函数的返回值为None
- return多个对象,解释器会把这多个对象组装成一个元组作为一个一个整体结果输出。
五 作用域
作用域介绍
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) #
# 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) #
代码执行成功,没有问题;在Java/C#中,执行上面的代码会提示name,age没有定义,而在Python中可以执行成功,这是因为在Python中是没有块级作用域的,代码块里的变量,外部可以调用,所以可运行成功;
作用域产生
>>> 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) #
这个是没有问题的,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使用在声明前了,所以报错
global关键字
当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了,当修改的变量是在全局作用域(global作用域)上的,就要使用global先声明一下,
nonlocal关键字
global关键字声明的变量必须在全局作用域上,不能嵌套作用域上,当要修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量怎么办呢,这时就需要nonlocal关键字了
代码如下:
count = 10
def outer():
global count
print(count) #
count = 100
print(count) #
outer()
print(count) # #nonlocal
def outer2():
count = 10
def inner():
nonlocal count
count = 20
print(count) #
inner()
print(count) #
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
六 内置函数
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)())#
print(next(tp)())#
print(next(tp)())#
print(next(tp)())#
Python函数篇的更多相关文章
- Python函数篇(5)-装饰器及实例讲解
1.装饰器的概念 装饰器本质上就是一个函数,主要是为其他的函数添加附加的功能,装饰器的原则有以下两个: 装饰器不能修改被修饰函数的源代码 装饰器不能修改被修改函数的调用方式 装饰器可以简单的理 ...
- Python函数篇(7)-正则表达式
1.正则表达式 正则表达式为高级的文本模式匹配,抽取,与/或文本形式的搜索和替换功能提供了基础,简单的来说,正则表达式是由一些字符和特殊符号组成的字符串.Python通过标准库中的re模块来支持正 ...
- python函数篇:名称空间、作用域和函数的嵌套
一.名称空间:(有3类) (1)内置名称空间(全局作用域) (2)全局名称空间(全局作用域) (3)局部名称空间(局部作用域) 关于名称空间的查询: x=1 def func(): print('fr ...
- Python函数篇:dict函数和列表生成式
1.dict函数语法:dict()dict(**kwarg) dict(mapping, **kwarg) dict(iterable, **kwarg) 第一种:dict()构造一个空字典 h=di ...
- Python函数篇:装饰器
装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理. ...
- Python函数篇(二)之递归函数、匿名函数及高阶函数
1.全局变量和局部变量 一般定义在程序的最开始的变量称为函数变量,在子程序中定义的变量称为局部变量,可以简单的理解为,无缩进的为全局变量,有缩进的是局部变量,全局变量的作用域是整个程序,而局部变量的作 ...
- Python函数篇(2)-递归函数、匿名函数及高阶函数
1.全局变量和局部变量 一般定义在程序的最开始的变量称为函数变量,在子程序中定义的变量称为局部变量,可以简单的理解为,无缩进的为全局变量,有缩进的是局部变量,全局变量的作用域是整个程序,而局部变量的作 ...
- Python函数篇(3)-内置函数、文件处理
1.内置函数 上一篇文章中,我重点写了reduce.map.filter3个内置函数,在本篇章节中,会补充其他的一些常规内置函数,并重点写max,min函数,其他没有说明的函数,会在后面写到类和面向对 ...
- Python函数篇(4)之迭代器与生成器
1.文件操作的"b模式"(补充) 在上一篇文章中,我在最后一部分写了文件处理的一些方法,但是觉得还是有必要再提一下如下的内容: 像rb.wb.ab这种模式,是以字节的形式操作,需要 ...
随机推荐
- 如何搭建ftp的yum源
ftp的yum的搭建步骤 第一步:安装vsftpd程序包(系统已经安装) [root@station40 ~]# rpm -qa |grep vsftpd vsftpd-2.2 ...
- ViewPager使用记录2——展示动态数据
ViewPager是v4支持库中的一个控件,相信几乎所有接触Android开发的人都对它不陌生.之所以还要在这里翻旧账,是因为我在最近的项目中有多个需求用到了它,觉得自己对它的认识不够深刻.我计划从最 ...
- 备忘:有MTU值设置不当导致的部分网站无法访问问题
如题,有时候突然weibo.com,webQQ等网站网络连接超时,怎么找也没得原因,今天管理电信的光猫,发现设置的MTU的1400,突然想起之前电脑和路由器上设置的MTU是1500,感觉可能是这个问题 ...
- 【ASP.NET MVC 学习笔记】- 09 Area的使用
本文参考:http://www.cnblogs.com/willick/p/3331519.html 1.ASP.NET MVC允许使用 Area(区域)来组织Web应用程序,这对于大的工程非常有用, ...
- 解决phpstorm ftp自动保存文件问题
初次使用phpstorm, 1.配置ftp时,远程文件要用/ftp用户名/文件夹名: 2.由于版本管理的原因(猜测),直接从本地原有文件修改时各种办法都无法上传,结果从服务器上下载一份再修改,解决这个 ...
- setsockopt()和getsockopt()函数参数
setsockopt()函数功能介绍 功能描述: 获取或者设置与某个套接字关联的选项.选项可能存在于多层协议中,它们总会出现在最上面的套接字层.当操作套接字选项时,选项位于的层和选项的名称必须给出.为 ...
- C# let 子句
在查询表达式中,存储子表达式的结果有时很有帮助,可在后续子句中使用. 可以通过 let 关键字执行此操作,该关键字创建一个新的范围变量并通过提供的表达式结果初始化该变量. 使用值进行初始化后,范围变量 ...
- Grunt参考
Grunt参考: http://www.cnblogs.com/yexiaochai/p/3603389.html http://blog.csdn.net/wangfupeng1988/articl ...
- font-face 在 Firefox无法正常工作问题
@font-face存在的问题: 1.不同浏览器支持不同格式 2.Firefox默认情况下不允许跨域font-face,除非你可以添加“Access-Control-Allow-Origin” hea ...
- ligerUI---ligerGrid中treegrid(表格树)的使用
写在前面: 表格树是在普通ligerGrid的基础上,做了一点改变,使数据以表格树的形式显示出来,适用于有级别的数据比如菜单(有父菜单,父菜单下面有子菜单).表格树的显示有两种方法,可以根据自己的项目 ...