Python—3.1、函数篇

1.1、命名空间

Python中一般有三种命名空间:

内置名称:Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。

全局名称:模块中定义的名称,记录了模块的变量、函数、类、其它导入的模块、模块级的变量和常量。

局部名称:函数中定义的名称,记录了函数的变量、参数和局部定义的变量。

  • 一个变量查找的顺序为:

局部的命名空间 -> 全局命名空间 -> 内置命名空间;

1.2、作用域

作用域就是一个 Python 程序可以直接访问命名空间的正文区域。
在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。

Python 的作用域一共有4种分别是:
L(Local):最内层,包含局部变量,比如一个函数/方法内部。

E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
G(Global):当前脚本的最外层,比如当前模块的全局变量。
B(Built-in): 包含了内建的变量/关键字等,最后被搜索。

规则顺序: L –> E –> G –> B。

在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

1.3、变量访问

1.3.1、全局和局部变量

#/usr/bin/python3
# coding=utf-8
from sys import path

ora_total=10

def chValue(newVaule):
    ora_total=newVaule
    return ora_total

print("the vaule of variable ora_total is {0} after changed:".format(chValue(30)))
print("then current value of variable ora_total is {0}:".format(ora_total))

#输出结果
the vaule of variable ora_total is 30 after changed
then current value of variable ora_total is 10

说明:在如上的代码中发现函数访问的ora_total 变量为函数内部的局部变量,没有改变模块中定义的全局变量;

变量申明

在Java和 c语言等,局部变量不能在外部使用;但是在Python中好像没有这个限制;

  • 局部申明
def varArea():
    try:
        list_a=[333,444,555]
        pass
    except Exception as e:
        print(e)

    print(list_a)


varArea()

输出结果:

[333, 444, 555]

Process finished with exit code 0
  • 提前申明
def varArea():
    list_a=None
    print(list_a)
    try:
        list_a=[333,444,555]
        pass
    except Exception as e:
        print(e)

    print(list_a)


varArea()

输出结果:

None
[333, 444, 555]

Process finished with exit code 0

1.3.2、global和nonlocal

  • 修改全局变量

当内部作用域想修改外部作用域的变量时,需要用到 global 和 nonlocal 关键字;

#/usr/bin/python3
# coding=utf-8
from sys import path


ora_total=10

def chValue(newVaule):
    global ora_total
    ora_total=newVaule
    return ora_total

print("the vaule of variable ora_total is {0} after changed".format(chValue(30)))
print("then current value of variable ora_total is {0}".format(ora_total))

#结果输出
the vaule of variable ora_total is 30 after changed
then current value of variable ora_total is 30

说明: 如上代码中函数内部申明访问的为全局变量,在赋值时需要另起一行,不能直接和申明全局变量放到同一行;

  • 修改嵌套作用域

如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字

#/usr/bin/python3
# coding=utf-8
from sys import path


def outerChValue(newVaule):
    lol_num=100
    print("the original value of local variable is {}".format(lol_num))
    def innerChValue(newValue):
        nonlocal lol_num
        lol_num=newVaule

    innerChValue(newVaule)
    print("the value of local variable is {} after changed".format(lol_num))


outerChValue(77)

#结果输出
the original value of local variable is 100
the value of local variable is 77 after changed

1.4、函数

1.4.0、语法格式

def funName(var_1,var_2,...var_n):
    # do something
    pass
    return $relult

参数传递分为值传递和引用传递;

  • 值传递
    值传递的参数对象为不可变对象,主要为字符串、数值、元组,传入的是对象的值,传入后原始对象和参数脱离关系;

  • 引用传递
    传入的是对象的引用,主要为列表、集合、字典等,在函数内部更改对象的值,外部对象值会同步改变;

说明:默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。

可更改(mutable)与不可更改(immutable)对象

  • 在 python 中,strings、tuples、numbers 是不可更改的对象,而 list、dict、set 等则是可以修改的对象。

  • 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个类型为int值为10的对象,再让 a 指向它,而 5 被丢弃,不是改变 a 的值;

  • 可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

1.4.1、参数传递

python 函数的参数传递:

  • 不可变类型:类似 C++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。
>>> 
>>> def change_para(a):
...     a+=5
...     return a
... 
>>> int_a=10
>>> change_para(int_a)
15
>>> print(int_a)
10
>>>
  • 可变类型:类似 C++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响
>>>
>>> def change_list(param):
...     del param[0]
...     return param
... 
>>> list_h=["aaa","bbb","ccc","ddd","eee"]
>>> change_list(list_h)
['bbb', 'ccc', 'ddd', 'eee']
>>> print(list_h)
['bbb', 'ccc', 'ddd', 'eee']
>>>
  • python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

1)关键字参数和默认值参数

>>> def infor_pet(name,place,age=3):
...     print("Age of your pet is %d,name of your pet is %s,place of your pet comes from %s "%(age,name,place))
... 
>>> infor_pet(place="market",name="Qzai")
Age of your pet is 3,name of your pet is Qzai,place of your pet comes from market 
>>>

说明:默认参数必须写在最后,对于无需返回值的函数,可以没有 return 语句;

2)不定长变量

  • 第一种:加 * 的元组参数
def cal_sum( arg1, *vartuple ):
    sum=arg1
    for x in vartuple:
        sum+=x
    return sum

cal_sum(10,20,30,40) 
  • 第二种:加 ** 的字典参数
def cal_sum( arg1, **varDict ):
    sum=arg1
    for x in varDict.values():
        sum+=x
    return sum

cal_sum(10,a=20,b=30,c=40) 

3)关键字参数
Python中声明函数时,参数中星号 * 可以单独出现,此时 * 后的参数必须用关键字传入。

def calVolume(length,width,*,heigth):
    volume=length*width*heigth
    return volume

# 错误调用方式
vol_1=(10,20,30)

# 正确调用方式
vol_2=(10,20,heigth=30)

1.4.2、lambda函数

Python 使用 lambda 来创建匿名函数,即不再使用 def 语句这样标准的形式定义的函数。
特点:
1)lambda 只是一个表达式,函数体比 def 简单很多;
2)lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。
3)lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。

语法规则:

lambda [arg1 [,arg2,.....argn]]:expression

示例代码:

>>> 
>>> fun_a=lambda a,b:a*b
>>> print(fun_a(4,5))
20

1.4.4、类型转换

  • int(x [,base])

  • float(x)

  • complex(real [,imag])

  • str(x)

  • repr(x)

  • eval(str)

  • tuple(s)

  • list(s)

  • set(s)

  • dict(d)

  • frozenset(s)
    功能:转换为不可变集合

  • chr(x)
    功能:将一个整数转换为一个字符

  • ord(x)
    功能:将一个字符转换为它的整数值

  • hex(x)
    功能:将一个整数转换为一个十六进制字符串

  • oct(x)
    功能:将一个整数转换为一个八进制字符串

1.4.5、随机函数

随机函数需要导入模块 random

import random
  • random.choice(seq)
  • random.randrange(start,stop,step)
  • random.random()
  • shuffle(lst)

1.4.6、返回值

Python的函数可以有多个返回值,实际通过 type 可以发现返回的是一个 tuple(元组) ;所以可以有多个参数接收 一个函数的多个返回值;

1.4.7、递归函数

def factorials(n:int):
    if(n<=0):
        sys.exit("请输入正整数参数")
    elif(n==1):
        return n
    else:
        return n * factorials(n-1)
  • 递归优化

递归函数对递归的层级有限制,当超出 栈的最大深度时将会抛出异常:

def levelSum(n:int):
    if(n<=0):
        sys.exit("请输入正整数参数")
    elif(n==1):
        return n
    else:
        return n + levelSum(n-1)
print(levelSum(1000))

输出结果:

D:\SoftWare\Python\python.exe E:/PythonProject/FileOperTest/funDemo01.py
Traceback (most recent call last):
  File "E:\PythonProject\FileOperTest\funDemo01.py", line 28, in <module>
    print(levelSum(1000))
  File "E:\PythonProject\FileOperTest\funDemo01.py", line 27, in levelSum
    return n + levelSum(n-1)
  File "E:\PythonProject\FileOperTest\funDemo01.py", line 27, in levelSum
    return n + levelSum(n-1)
  File "E:\PythonProject\FileOperTest\funDemo01.py", line 27, in levelSum
    return n + levelSum(n-1)
  [Previous line repeated 995 more times]
  File "E:\PythonProject\FileOperTest\funDemo01.py", line 22, in levelSum
    if(n<=0):
RecursionError: maximum recursion depth exceeded in comparison

Process finished with exit code 1

1.4.8、名称获取

某些场景下,在函数内部需要获取或输出函数自己的名称信息,此时可以通过 sys._getframe().f_code.co_name获取;

import sys


def recordTest():
    print("current step is in function {}!".format(sys._getframe().f_code.co_name))


if __name__ == "__main__":
    print("the module app is running!")

    recordTest()

控制台输出:

the module app is running!
current step is in function recordTest!

Process finished with exit code 0

1.5、模块

1.5.1、模块导入

模块导入方式如下三种:

from module import fun1,fun2,fun3
from module import *
import module

__name__属性
一个模块被其他程序第一次引入时,其主程序将运行。如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行。

#!/usr/bin/python3
def DisplayCore():
    if __name__=="__main__":
        print("My main function body is running!")
    else:
        pass
    
    return

说明: 每个模块都有一个__name__属性,当其值是"__main__"时,表明该模块自身在运行,否则是被引入。

说明:__name__ 与 __main__ 底下是双下划线, _ _ 是这样去掉中间的那个空格。

1.5.2、包导入

  • 方式一:
from pkg_par.pkg_son.module import fun1

说明:这种导入方式 函数 fun1 可以直接使用;

  • 方式二:
from  pkg_par.pkg_son import module.fun1

说明:这种导入方式 函数 fun1 需要按照 module.fun1 的方式使用;

  • 方式三:
import pkg_par.pkg_son.module.fun1

说明:这种导入方式 函数 fun1 需要按照全路径使用:pkg_par.pkg_son.module.fun1;

强调:模块相对路径导入只能使用 from xx.xx.xx import xx 的方式;不能直接使用 import ..xx.xx.xx 的方式;

1.6、偏函数

Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。

简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

如:max2 = functools.partial(max, 10)
等同于

args = (10, 5, 6, 7)
max(*args)

================================ over ========================================
上一篇:Python—2、对象操作
下一篇:Python—8、面向对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值