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语句把结果返回

注意:

  1. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,也可以理解为 return 语句代表着函数的结束
  2. 如果未在函数中指定return,那这个函数的返回值为None
  3. 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) #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中是没有块级作用域的,代码块里的变量,外部可以调用,所以可运行成功;

作用域产生

>>> 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使用在声明前了,所以报错

 global关键字

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

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

六 内置函数

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
时间: 2024-08-29 03:12:01

Python函数篇的相关文章

Python函数篇(7)-正则表达式

1.正则表达式 ??正则表达式为高级的文本模式匹配,抽取,与/或文本形式的搜索和替换功能提供了基础,简单的来说,正则表达式是由一些字符和特殊符号组成的字符串.Python通过标准库中的re模块来支持正则表达式. 2.特殊符号和字符 ??首先介绍一下最常见的特殊符号和字符,即所谓的元字符. 表示法 描述 正则表达式用法示例 literal 匹配文本字符串的字面值literal re.findall("chen","sadchen21") . 匹配任意字符(除了\n之外

python函数篇0-1

创建类和对象 面向对象编程是一种编程方式,此编程方式的落地需要使用 "类" 和 "对象" 来实现,所以,面向对象编程其实就是对 "类" 和 "对象" 的使用. 类就是一个模板,模板里可以包含多个函数,函数里实现一些功能 对象则是根据模板创建的实例,通过实例对象可以执行类中的函数 class是关键字,表示类 创建对象,类名称后加括号即可 ps:类中的函数第一个参数必须是self(详细见:类的三大特性之封装) 类中定义的函数叫做

python函数篇0-2

函数的有三中不同的参数: 普通参数 默认参数 动态参数# ######### 定义函数 ######### # name 叫做函数func的形式参数,简称:形参def func(name):    print (name) # ######### 执行函数 ######### #  'fuyuteng' 叫做函数func的实际参数,简称:实参func('fuyuteng') def func(name, age = 18): print ("%s:%s" %(name,age)) #

第六篇:Python函数进阶篇

在了解完了 Python函数基础篇之后,本篇的存在其实是为了整合知识,由于该篇的知识是否杂乱,故大家可以通过点开点连接直接进入其详细介绍,该篇主要大致的介绍一下几个知识点:  一.Python的迭代器和生成器 二.Python的内置函数 三.Python的open函数之文件处理 四.Python的递归函数 五.Python的高阶函数 六.Python的装饰器 一.Python的迭代器和生成器: 本篇我们介绍可迭代对象和迭代器对象--包括两者的定义及区别.为什么要有迭代器对象,其的用法是怎么样的

计算机二级python 知识点篇(函数与代码复用)

计算机二级python 知识点篇(函数与代码复用) 全局变量 全局变量指在函数之外定义的变量, 在程序执行全过程有效. 全部变量在函数内部使用时, 需要提前使用保留字global声明, 语法形式如下: global <全局变量> >>>n = 2 #n是全局变量 >>>def multiply(x, y = 10): global n return x*y*n # 使用全局变量n >>>s = multiply(99, 2) >>

【Python之旅】第三篇(一):Python函数

说明: 使用函数可以使程序实现功能模块化,大大简洁我们的程序,这里主要讨论Python中函数的下列内容: 1.函数定义与函数参数 2.局部变量和全局变量 3.函数默认参数和关键参数 4.*Args和**Kargs 因为函数部分内容跟C语言中的很多内容都十分相似,所以会结合C语言来进行对比学习. 1.函数定义与函数参数 --基本格式1:不参参数 ·定义: def sayHi():     print "Hello!" ·调用: >>> sayHi() Hello --基

Python基础篇【第2篇】: Python自定义函数

Python函数 1. 函数定义 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创建函数,这被叫做用户自定义函数. 2. 定义 函数代码块以def关键词开头,后接函数标识符名称和圆括号(). 任何传入参数和自变量必须放在圆括号中间.圆括号之间可以用于定义参数. 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明. 函数内容以冒号起始,并且缩进. R

【Python基础学习篇八】Python函数

函数是一段可以重复多次调用的代码,通过输入的参数值,返回需要的结果. 一.函数的定义 函数的定义使用保留字def定义.函数在使用前必须定义,函数的类型即返回值的类型. Python函数定义的格式如下: def 函数名 (参数1[=默认值1],参数2[=默认值2]...): ... return 表达式 函数名可以是字母.数字或下划线组成的字符串,但不能以数字开头.函数的参数放在一对圆括号中,参数的个数可以有一个或多个,参数之间用逗号隔开,这种参数称之为形式参数. 例子: #!/usr/bin/e

第三篇:python函数

1.python函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创建函数,这被叫做用户自定义函数. 2.函数分类 1.内置函数 2.自定义函数 3.为什么要定义函数 函数即变量,变量必须先定义后使用,未定义而直接引用函数,就相当于在引用一个不存在的变量名 代码演示? 4.定义一个函数 你可以定义一个由自己想要功能的函数,以下是简单的规则: 函数代码块以