python基础-函数

4748次阅读 328人点赞 作者: WuBin 发布时间: 2024-06-19 17:27:35
扫码到手机查看

函数

下面是一个最基本的函数

def greet():
    print('esay')

greet()

再看一个例子

def animals(name, age):
    print('动物的年龄是' + str(age) + '岁,名字是' + name)

animals('dog', 3)
animals(age = 5, name = 'cat')

形参与实参

animals(name, age)中,name和age是形参;而animals('dog',3)中的('dog',3)是实参。

实参又可以分为位置实参和关键字实参。

// 位置实参
animals('dog', 3) 传入的参数顺序与形参的顺序相同

// 关键字实参
animals(age = 5, name = 'cat') 通过关键字关联实参与形参的对应,顺序不重要

设置函数默认参数值

def animals(name, age = 16):
   xxx

让函数返回处理结果,并给其设置默认参数

def connect_name(firstName, lastName, middleName = ''):
    if middleName:
        fullName = firstName + middleName + lastName
    else:
        fullName = firstName + lastName
    return fullName

print( connect_name('wu', 'bin') )
print( connect_name('wu', 'tong', 'tong') )

同样的函数也能返回字典

def getDirr(first, last):
    obj = { 'first': first, 'last': last }
    return obj

print( getDirr('wu', 'bin') )
注意 函数中 不能写 return obj = {'..': xxxx} 连起来写就会报错 必须像上面例子那样分行写

结合while实现一个用户输入姓名,然后返回名字的功能,输入q则结束循环

def inputerYourName(first, last):
    fullName = first + ' ' + last;
    return fullName.title()

while True:
    print('请告诉我你姓什么:')
    print('输入q会跳出循环')

    fname = input('姓')
    if fname == 'q':
        break

    lname = input('名')
    if lname == 'q':
        break

full_name = inputerYourName(fname, lname)
print(full_name)

函数中是可以修改传入的列表的

将列表传递给函数后,函数就可以对其进行修改,而且函数对这个列表所做的任何修改都是永久性的!

下面看一个例子

def print_works(works, finishs):
    # 遍历数组 直到遍历完所有元素
    while works:
        # 从数组末尾中取一个项 pop()会从works列表末尾移除最后一项 并返回
        currentWork = works.pop()
        print('正在做的是' + currentWork)
        finishs.append(currentWork)

def show_finish(finishs):
    print('以下是全部完成的工作')
    for finish in finishs:
        print(finish)

works = ['#1工作', '#2work', '#3work', '#4work']
finishs = []

print_works(works, finishs)
show_finish(finishs)
正在做的是#4work
正在做的是#3work
正在做的是#2work
正在做的是#1工作
-----------以下是全部完成的工作--------
#4work
#3work
#2work
#1工作
pop()会从数组中移除最后一项,并返回被移除的项,直到works为空

上面就是最终运行的结果,可以发现,数组变量已经被修改了

哪怕我修改变量名,结果也是一样

works_ppp = ['#1工作', '#2work', '#3work', '#4work']
finishs_ppp = []

print_works(works_ppp, finishs_ppp)
show_finish(finishs_ppp)

再来看一个更好理解的例子

def changelist(nums):
    for item in nums:
        # item = item + 1 这样写不会改变传递进来的nums数组
        nums[item - 1] = item + 1

testlist = [1, 2, 3, 4]
changelist(testlist)
print(testlist)

最终输出的结果就是:[2, 3, 4, 5],testlist被改变了!

但是,如果在函数中,使用单纯的赋值,是改变不了传入的列表的!

def changelist(nums):
    newarr = []
    for item in nums:
        item = item + 1 
        newarr.append(item)
    nums = newarr // 赋值会改变nums,但不会改变外部的testlist
    print(nums)
    print('---')

testlist = [1, 2, 3, 4]
changelist(testlist)
print(testlist)

运行结果

[2, 3, 4, 5]
---
[1, 2, 3, 4]
所以结论就是,如果要在函数内部修改传入的外部列表,只有直接修改传入列表中的项才可以

禁止函数修改传入的列表

解决这个问题很简单,只要让传入的是一个列表的副本就行

function_name(list_name[:])

切片表示法[:] 代表创建一个列表的副本,比如上面例子中,如果不想要清空外部的工作列表works,可以像下面这样使用:

def print_works(works, finishs):
    # 遍历数组 直到遍历完所有元素
    while works:
        # 从数组末尾中取一个项
        currentWork = works.pop()
        print('正在做的是' + currentWork)
        finishs.append(currentWork)

def show_finish(finishs):
    print('-----------以下是全部完成的工作--------')
    for finish in finishs:
        print(finish)

works = ['#1工作', '#2work', '#3work', '#4work']
finishs = []

print_works(works[:], finishs)
show_finish(finishs)

print('=========以下是原本works===========')
print(works)

运行结果

正在做的是#4work
正在做的是#3work
正在做的是#2work
正在做的是#1工作
-----------以下是全部完成的工作-------- 
#4work
#3work
#2work
#1工作
=========以下是原本works===========     
['#1工作', '#2work', '#3work', '#4work']

通过传入副本,让原本的works中的数据没有被删除。没有影响外部的列表。

建议:还是推荐将原始列表传递给函数,因为让函数使用现成列表可以避免花时间和内存创建副本,从而提高效率,特别是列表比较大的时候。

任意数量的实参

当预先不知道需要接收多少实参时,使用*形参名,无论传入多少实参,都会被其接收,如下

def make_cook(*toppings):
    print(toppings)

make_cook('面条', '米饭')
make_cook('大头菜', '馒头', '鸡肉', '等等更多')
topping可以是任意名称,*everyname

最终打印结果

('面条', '米饭')
('大头菜', '馒头', '鸡肉', '等等更多')

形参名*topping中的*让py创建了一个名为topping的空元组,并将接收到的所有值都封装到这个元组中。

即使一个值也会如此,比如('面条')

因此接下来就可以对元组进行遍历,以处理传入的所有参数。

def make_cook(*everyname):
    print(everyname)
    for name in everyname:
        print('=' + name)

make_cook('面条', '米饭')
make_cook('大头菜', '馒头', '鸡肉', '等等更多')

结果

('面条', '米饭')
=面条
=米饭
('大头菜', '馒头', '鸡肉', '等等更多')
=大头菜
=馒头
=鸡肉
=等等更多

结合位置实参和任意数量实参

注意,任意数量的形参,比如放在最后

def make_cook(size, *everyname):
    print('要做的菜尺寸是' + str(size))
    for name in everyname:
        print('=' + name)

make_cook(16, '大头菜', '馒头', '鸡肉', '等等更多')
要做的菜尺寸是16
=大头菜
=馒头
=鸡肉
=等等更多

有时候,需要接收任意数量的实参,但预先不知道传递给函数的会是什么样的信息,这时,可将函数编写成能接受任意数量的键值对。

比如,将收到用户有关信息,但不确定是什么样的信息。

def build_profile(first, last, **user_info):
    # 创建一个字典
    profile = {}
    profile['first'] = first
    profile['last'] = last
    for key, value in user_info.items():
        profile[key] = value
    return profile

user_profile = build_profile(
    'wu',
    'bin',
    age = 35,
    sex = '男',
    job = '信网'
)

print(user_profile)

此函数要求提供姓名,以及允许用户根据需求提供任意数量的 名称=“值”,这样形式的键值对。

形参**user_info中的两个星号让py创建一个名为user_info的空字典,并将所有接收到的 名称=值 都封装到这个字典中,可以像访问其他字典那样访问user_info中的名称=值对。

在build_profile函数中,将固定的姓名首先加入字典,其次遍历**user_info字典中的键值对,将每个属性以及对应的值也加入到profile字典中,最后返回这个字典。

结果:{'first': 'wu', 'last': 'bin', 'age': 35, 'sex': '男', 'job': '信网'}

在实际开发中,可以混用位置实参、关键字实参、任意数量实参。

函数存储在模块中

函数可以存储在独立的文件中,叫做模块。

import允许当前主程序中使用模块中的代码。

在同一个目录下创建两个文件,test.py和fns.py

在fns.py中写函数:

def funtest(num):
    print( num + 1 )

在test.py中

import fns # 引入整个函数模块
# 调用fns文件中的函数
fns.funtest(2)

使用import导入了名为module_name.py的整个模块,就可以使用

module_name.function_name()

来使用其中任何一个函数。

导入特定的函数

from module_name import function_name

还可以用逗号分隔函数名,从模块中导入任意数量的函数

from module_name import function_0, function_1, function_2

比如,fns.py

def fun1(num):
    print( num + 1 )

def fun2(num):
    print(num - 1)

test.py

from fns import fun1

fun1(2)
from fns import fun1, fun2

fun1(2)
fun2(10)

使用这种形式的时候,就不用使用fns.xx了,因为都已经显示的导入了函数,所以就无需再指定其名称了。

使用别名as

如果导入的函数名与现有的函数名有冲突,那么就使用as起一个别名。

from fns import fun1 as lovew, fun2 as love

lovew(2)
love(4)

使用as给模块指定别名

给模块指定别名,可以更加简短的使用模块

import fns as small

small.fun1(5)

使用*导入模块中的所有函数

from fns import *

fun1(5)

非自己编写的模块文件,不建议这么用,因为会发生函数名冲突。

函数名规范

函数或者模块命名时,只在其中使用小写字母和下划线,

给形参指定默认值时,等号两边不要有空格

def function_name(param_0, param_1='default'):

在函数调用中的实参,也要遵守这个约定

function_name('1', param_1=20)

一般代码行长度不要超过79个字符,如果参数太长

def function_name(
        param1, param2,
        param3, param4
):
         ...

所有的Import都应该写在文件开头

点赞 支持一下 觉得不错?客官您就稍微鼓励一下吧!
关键词:def
推荐阅读
  • uniapp实现被浏览器唤起的功能

    当用户打开h5链接时候,点击打开app若用户在已经安装过app的情况下直接打开app,若未安装过跳到应用市场下载安装这个功能在实现上主要分为两种场景,从普通浏览器唤醒以及从微信唤醒。

    8686次阅读 558人点赞 发布时间: 2022-12-14 16:34:53 立即查看
  • Vue

    盘点Vue2和Vue3的10种组件通信方式

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异;本文将通过选项式API组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式。

    3624次阅读 271人点赞 发布时间: 2022-08-19 09:40:16 立即查看
  • JS

    几个高级前端常用的API

    推荐4个前端开发中常用的高端API,分别是MutationObserver、IntersectionObserver、getComputedstyle、getBoundingClientRect、requ...

    13644次阅读 881人点赞 发布时间: 2021-11-11 09:39:54 立即查看
  • PHP

    【正则】一些常用的正则表达式总结

    在日常开发中,正则表达式是非常有用的,正则表达式在每个语言中都是可以使用的,他就跟JSON一样,是通用的。了解一些常用的正则表达式,能大大提高你的工作效率。

    12457次阅读 411人点赞 发布时间: 2021-10-09 15:58:58 立即查看
  • 【中文】免费可商用字体下载与考证

    65款免费、可商用、无任何限制中文字体打包下载,这些字体都是经过长期验证,经得住市场考验的,让您规避被无良厂商起诉的风险。

    10879次阅读 873人点赞 发布时间: 2021-07-05 15:28:45 立即查看
  • Vue

    Vue3开发一个v-loading的自定义指令

    在vue3中实现一个自定义的指令,有助于我们简化开发,简化复用,通过一个指令的调用即可实现一些可高度复用的交互。

    14963次阅读 1192人点赞 发布时间: 2021-07-02 15:58:35 立即查看
  • JS

    关于手机上滚动穿透问题的解决

    当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。在PC上使用css即可解决,但是在手机端,情况就变的比较复杂,就需要禁止触摸事件才可以。

    14516次阅读 1182人点赞 发布时间: 2021-05-31 09:25:50 立即查看
  • Vue

    Vue+html2canvas截图空白的问题

    在使用vue做信网单页专题时,有海报生成的功能,这里推荐2个插件:一个是html2canvas,构造好DOM然后转canvas进行截图;另外使用vue-canvas-poster(这个截止到2021年3月...

    28147次阅读 2213人点赞 发布时间: 2021-03-02 09:04:51 立即查看
  • Vue

    vue-router4过度动画无效解决方案

    在初次使用vue3+vue-router4时候,先后遇到了过度动画transition进入和退出分别无效的情况,搜遍百度没没找到合适解决方法,包括vue-route4有一些API都进行了变化,以前的一些操...

    24329次阅读 1871人点赞 发布时间: 2021-02-23 13:37:20 立即查看
交流 收藏 目录