程序猿阵线联盟-汇总各类技术干货程序员

Python Learning-函数 二

2018-08-27  本文已影响8人  东南有大树

如果列表被当作参数传递给函数后,被莫名的修改掉,再次使用列表时,其中的元素已经生了改变,有没有什么方法可以控制列表不被改变呢?

例一:

# 食物列表 
foods = ['tomato', 'potato', 'onion','apple', 'banana']

def print_food(food_list):
    """打印食物名称"""
    
    # 循环,如果food_list是空将返回False
    while food_list:
        print(foods.pop())
    # 循环完毕后将列表副本打印
    print(food_list)

# 打印原来的列表,以作对比
print(foods)

输出:

banana
apple
onion
potato
tomato
[]
['tomato', 'potato', 'onion', 'apple', 'banana']

可见,函数体中修改的是foods列表的副本而已,对原列表没有影响,但是这种情况也不是绝对的,请看下面示例

例二:

# 食物清单
foods = [
    {'tomato': 3, 'potato': 2, 'onion': 4},
    {'apple': 5, 'banana': 3.3},
    {'beef': 23, 'pork': 14, 'chicken': 19.8, 'fish': 9.7}
]


def print_food(food_list):
    """打印foods列表中的食物名称"""

    for food_dic in food_list:
        for food in food_dic.keys():
            # 将打印完毕的食物的价格改为0
            food_dic[food] = 0

    # 循环完毕后将列表副本打印出来,以作对比
    print(food_list)

# 将foods列表的副本传递给函数
print_food(foods[:])
# 打印原列表
print(foods)

输出:

[{'tomato': 0, 'potato': 0, 'onion': 0}, {'apple': 0, 'banana': 0}, {'beef': 0, 'pork': 0, 'chicken': 0, 'fish': 0}]
[{'tomato': 0, 'potato': 0, 'onion': 0}, {'apple': 0, 'banana': 0}, {'beef': 0, 'pork': 0, 'chicken': 0, 'fish': 0}]

结果显示,不管是原来的列表还是创建的副本列表,其price都被修改成了0,这是为什么呢?

是因为列表中包含三个字典,而字典是引用类型,那引用类型为什么会影响两个对象呢?请看下面解释

python的值类型和引用类型

也就是说,值类型提供的值本身,而引用类型提供的是指向值的一个引用地址;再看上面的例子,因为字典是个引用类型,所以foods列表与其副本中所装的三个字典都来字相同对象的引用,于是,在更改副中字典的元素后,实际上也影响到了原列表

匿名函数

Python 使用 lambda来创建匿名函数

匿名是指不需要使用def定义函数与函数名称

例:

# 定义一个返回"Hello, XXX!"的函数
def say_hello(name):
    """返回Hello语句"""
    
    message = "Hello, "+name+"!"
    return message

# 打印函数返回的字符串
print(say_hello("xiaohong"))

# -----------------------------

# 定义一个lambda表达式,并将该函数赋值给变量g
g = lambda name : "Hello, "+name+"!"
# 打开匿名函数
print(g("xiaoming"))

输出:

Hello, xiaohong!
Hello, xiaoming!

lambda定义的匿名函数又叫lambda表达式,它只有一行代码

格式:lambda [arg1 [,arg2,.....argn]]:expression,冒号前面的是可选的参数,冒号之后的语句是代码块,该代码块执行的结果将被返回,因此lambda表达式没有return语句

再举个例子:

# 食物清单 
foods = [
    {'tomato': 3, 'potato': 2, 'onion': 4},
    {'apple': 5, 'banana': 3.3},
    {'beef': 23, 'pork': 14, 'chicken': 19.8, 'fish': 9.7}
]

for food_dic in foods:
    # 将食物的价格翻倍,通过lambda表达式返回价格的列表
    x = [price*2 for price in food_dic.values()]
    # 打印列表
    print(x)

在《列表的更多操作》一节中,讲过列表解析,其实就是使用了匿名函数,即lambda表达式

传递任意数量的参数

在不知道传递的参数到底有多少个,除了可以使用列表之外,还可以这样写:

# 食物列表
# foods = ['tomato', 'potato', 'onion','apple', 'banana']

def print_food(*foods):
    """打印食物名称"""

    # 打印看看
    print(foods)

# 打印原来的列表,以作对比
print_food('apple', 'pear', 'milk')

输出:

('apple', 'pear', 'milk')

在形参foods之前加一个*号,表示创建了一个名为foods的无组,然后将传来的所有实参都装进这个无组中

同理,Python也允许以相同的方式创建一个字典来接收键值对形式的多个参数

# 食物列表
# foods = ['tomato', 'potato', 'onion','apple', 'banana']

def print_food(name,**foods):
    """打印食物名称"""

    # 打印看看
    print(foods)

# 打印原来的列表,以作对比
print_food('xiaoming', apple=2, pear=3, milk=2.5)

输出:

{'apple': 2, 'pear': 3, 'milk': 2.5}

两个*号表示创建一个字典,并将所有传来的参数装进该字典中去;因此实参的形式必须以key=value这种形式传递

注意:字典的key不能重复,apple虽然是字符串,但实参这里不需要给它加引号

从上例中也可以看出,函数中可以现时存在不同形式的形参与实参,因此传递实参可以按照位置匹配的方式进行传递,所以将能接收任意数量实参的形参放在最后

将函数封装进模块中

还可以将函数封装进模块当中,与主程序进行分离开;在使用的时候,只要从相应的模块当中导入即可

在保存Python文件的时候,文件后缀需要以.py结尾,以.py结尾的文件就是模块

例,将下面代码保存到hello.py文件中

def say_hello(name):
    """say hello 语句"""

    print(("hello, " + name + "!").title())


def print_foods():
    """打印食物清单中的食物名称"""

    # 食物列表
    foods = ['tomato', 'potato', 'onion', 'apple', 'banana']
    # 打印
    for food in foods:
        print(food)

然后在同一目录下,再新建一个main.py文件,其中代码如下:

# 导入hello模块
import hello  

# 调用hello模块下的say_hello函数
hello.say_hello('jack')

输出:

Hello, Jack!

通过符号.来调用相应模块下的函数;通过.可以访问到模块下的所有函数

调用print_foods()函数

# 导入hello模块
import hello  

# 调用hello模块下的say_hello函数
# hello.say_hello('jack')
hello.print_foods()

输出:

tomato
potato
onion
apple
banana

不仅可以导入模块,还可以直接导入模块中的函数

# 导入hello模块中的函数
from hello import say_hello

# 调用hello模块下的say_hello函数
say_hello('jack')

其语法是:form x import x从某模块下导入一个函数

如果要导入多个函数,如下:

# 导入hello模块中的函数
from hello import say_hello, print_foods

# 直接调用函数
say_hello('jack')
print_foods()

输出:

Hello, Jack!
tomato
potato
onion
apple
banana

如果导入了模块中的函数,在使用的时候则不需要通过.来从模块中访问函数

如果要导入模块下的全部函数,如下:

# 导入hello模块中的函数
from hello import *

# 直接调用函数
say_hello('jack')
print_foods()

*表示导入模块下的所有函数

为模块与函数重命名

import hello as ho
from hello import say_hello as sh

ho.say_hello('jack')
sh('jack')

输出:

Hello, Jack!
Hello, Jack!

在实际开发中,某个导入的模块可能会用得很多,如果名字非常长,使用起来不方便,所以重命名可以让代码更加的简洁、实用

目录
上一章 Python Learning-函数 一
下一章 Python Learning-面向对象编程-类 一

上一篇下一篇

猜你喜欢

热点阅读