python学习笔记--3.函数

23-函数基本介绍

#函数:通俗理解就是某一个“功能”的代码实现
def show():
    print("哈哈哈")
    print("哈哈哈")

show()
运行结果:
哈哈哈
哈哈哈

#函数定义的格式
#def 函数名(参数【可选】):
     #功能代码的实现
 
#定义函数不会调用
def show():
    print("哈哈哈")
运行结果:
Process finished with exit code 0

#调用函数的方式--函数名(参数)

#定义带有参数的函数
#name,age:形式参数(函数定义带有的参数叫形式参数)-形参
def show_msg(name,age):
    print(name,age)
#调用带有参数的函数“朱杰”,18:为实际参数-实参
show_msg("朱杰",18)
运行结果:朱杰 18

24-函数的四种类型(断点使用)

#无参数无返回值的函数(函数体里面的代码执行完毕,返回到函数的调用处)
def show():
    print("好冷")
show()
运行结果:好冷

#无参数有返回值的函数(带着数据返回到代码的调用处)
def show():
    result = 10
    return result

value = show()
print(value)
运行结果:10

#有参数无返回值的函数
def show(a,b):
    print(a,b)
show(1,2)
运行结果:1 2

def show(name,age):
    print("我叫:%s 年龄:%d" % (name,age))
show("朱杰",2)
运行结果:我叫:朱杰 年龄:2

#有参数有返回值的函数
def show_msg(name,age):
    msg ="我叫:%s 年龄:%d" % (name,age)
    return msg
result = show_msg("朱杰",8)
print(result)
运行结果:我叫:朱杰 年龄:8

#在此代码片中使用断点,先设置断点,再debug
1 def show():
2     print("哈哈")
3 print("呵呵")
4 show()
执行顺序:1->3->4->1->2-4->结束
#总结:函数调用的时候会返回到函数的定义处,执行函数体里面的代码
#执行完毕,返回到调用处

25-局部变量

#局部变量:在函数内定义的变量叫局部变量,局部变量只能在函数里使用
def show():
    score = 100
    print(score)
show()
运行结果:
100
def show():
    score = 100
    print(score)
print(score)
运行结果:
NameError: name 'score' is not defined

26-全局变量

#全局变量:在函数外定义的变量叫全局变量
#特点:全局变量可以在不同的函数里面使用
score = 100
def show():
    print(score)
show()
运行结果:
100

#局部变量和全局变量重名时
score = 100
def show():
    #定义了一个局部变量,只是这个局部变量和全局变量的名字一样
    score =99
    print(score)

show()
print(score)
运行结果:
99
100

#将函数内的局部变量变为全局变量
score = 100
def show():
    global score#当要对全局变量score重新赋值时
    score =99
    print(score)

show()
print(score)
运行结果:
99
99

27-调用函数的传参方式

#1.使用位置传参
def show(name,age):
    print(name,age)
#1.使用位置参数方式传参:必须按照函数的参数顺序传参
show("朱杰")#丢失了一个位置参数
运行结果:
TypeError: show() missing 1 required positional argument: 'age'
show(19,"朱杰")
运行结果:
19 朱杰

# 2.使用关键字方式传参
def show(name,age):
    print(name,age)
show(age=19,name="朱杰")
运行结果:
朱杰 19

28-函数的不定长参数–调用函数时不确定传入多少个参数

#不定长位置参数的函数的定义与调用
def sum_num(*args):
    #提示:args:会把调用函数传入的位置参数封装到一个元组里面
    print(args,type(args))
    #计算结果变量
    result = 0
    for value in args:
        result+= value
    return result
sum = sum_num(3,3,5)
print(sum)
运行结果:
(3, 3, 5) <class 'tuple'>
11

#不定长关键字参数的函数的定义与调用
#**kwargs 代表不定位置参数
def show_msg(**kwargs):
    print(kwargs,type(kwargs))
    for key,value in kwargs.items():
        print(key,value)
#调用不定长位置参数的函数
show_msg(a= 3,b=5)
运行结果:
{'a': 3, 'b': 5} <class 'dict'>
a 3
b 5

29-断点的使用

在此要打断点处的代码前点击,出现红色园,此时debug该代码,点击step over键,此程序会逐行的运行,一步一步的运行,看代码运行至哪里

30-缺省参数

#缺省参数:在函数定义的时候参数就有值(默认值)
#此参数就叫做缺省参数
#如果不给缺省参数的参数传值,那么使用默认值
#如果传值,使用新传的值做计算
#如果有必选参数和缺省参数,缺省参数必须放到必选参数后面

def sum_num(num1,num2=2):
    result = num2+num1
    return result

value = sum_num(3)
print(value)
运行结果:5

31-定义不定长位置参数的使用

#函数嵌套,使用传入的参数
def show_msg(*args):
    print(args)

def show(*args):
    print(args,type(args))
    show_msg(args)
show(1,2)
运行结果:
(1, 2) <class 'tuple'>
((1, 2),)

#函数嵌套,使用自己的输入
def show_msg(*args):
    print(args)

def show(*args):
    print(args,type(args))
    show_msg(5,8)
show(1,2)
运行结果:
(1, 2) <class 'tuple'>
(5, 8)

#函数嵌套,对元组进行拆包
def show_msg(*args):
    print(args)

def show(*args):
    print(args,type(args))
    show_msg(*args)
show(1,2)
运行结果:
(1, 2) <class 'tuple'>
(1, 2)

32-函数多种参数传参方式

def show(name,age,*args,**kwargs):
    print(name,age,args,kwargs)
#不能使用下列方式调用,因为前面的使用了关键字传参,后面不能使用位置传参)
#show(name = "李四",age = 18, 1,4,c=1,b=2)
show("李四",20,1,2,3,4,a="苹果",b="香蕉")
运行结果:
李四 20 (1, 2, 3, 4) {'a': '苹果', 'b': '香蕉'}

#位置参数在前的传参方式
def show(*args,name,age,**kwargs):
    print(name,age,args,kwargs)
#不能使用下列方式调用,因为前面的使用了关键字传参,后面不能使用位置传参)
#show(name = "李四",age = 18, 1,4,c=1,b=2)
show(1,2,name="哈哈",age=33,aa=1,nn=2)
运行结果:
哈哈 33 (1, 2) {'aa': 1, 'nn': 2}

33-函数的注意事项

#1.函数名不能相同
#如果定义了第二个函数和第一个函数名相同,那么第一个函数不能使用,覆盖了

#2,变量命名和函数名不能相同

#函数里用pass就不报错,直接pass过去
def show():
    pass
#里面啥也不执行

34-规定必须使用关键字传参的方法

#注意点:*后面的参数,必须使用关键字传参方式
def callAble(address,sex,*,name,age):
    print(address,sex,name,age)
callAble("上海","男",name="刘燕",age=20)
运行结果:
上海 男 刘燕 20

35-函数嵌套:在函数里再定义一个函数

def call_able():
#函数内的函数不能在外部使用
    def text():
        print("我是嵌套函数")
    text()
call_able()
运行结果:
我是嵌套函数

36-匿名函数

可以使代码更加精简,简化命名,当有的函数只调用1,2次就不必建函数

#原函数
def ds(x):
    return 2*x +1
print(ds(6))
运行结果:
13

#匿名函数(lambda)
ds =lambda x:2*x+1 将计算后的值return给ds
print(ds(6))
运行结果:
13

#原函数
def odd(x):
    return x%2
temp = range(10)
show = filter(odd,temp)#filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。该接收两个参数,第一个为函数,第#二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
print(show,type(show))
print(list(show))
运行结果:
<filter object at 0x0000026F4374B320> <class 'filter'>
[1, 3, 5, 7, 9]

#匿名函数
print(list(filter(lambda x:x%2,range(10))))
运行结果:
[1, 3, 5, 7, 9]

37-函数和模块开发(import)

1)导入整个模块文件
函数的优点之一是可以将代码块与主程序分离,通过给函数指定描述性的名称,能够让主程序更加容易理解。
另外,可以进一步将函数存储在称为模块的独立文件中,再将模块导入到主程序中。
import语句允许在当前运行的程序文件中使用模块中的代码。
将函数存储在独立的文件中,其好处之一是隐藏程序代码的细节,将重点放在程序的高层逻辑上。
好处之二可以在众多不同的程序里可以重用这个函数,将函数存储在独立的文件中后,可以与其他程序员共享这些文件而不是整个程序。初学者学会了导入函数的方法后,还可以让开发者使用其他程序员编写的函数库,这最常见的就是python提供的内置函数。
如何导入整个函数模块?
1.先创建一个模块,模块的扩展名是".py"格式的文件,例如:pizza.py
2.在创建的模块中,创建一个函数,例如:make()
3.在另一个独立的文件making.py中调用文件pizza.py中的函数make(),在调用的时候调用了整个pizza.py文件
比如:实例文件pizza.py的功能是编写函数make(),实现制作披萨的功能:
–pizza.py–

def make(size,*toppings):
    print("\n制作一个"+str(size)+"寸的披萨需要的配料:")
    for topping in toppings:
        print("- "+topping)

实例文件making.py的功能是,使用import语句会调用外部模块文件pizza.py,然后使用文件pizza.py中的函数make()实现制作披萨的功能
–making.py–

import pizza
pizza.make(16,'黄油','虾','芝士')
pizza.make(12,'黄油')

运行结果:
制作一个16寸的披萨需要的配料:
黄油

芝士

制作一个12寸的披萨需要的配料:
黄油
在上述代码中,当python读取此文件时,通过第一行代码import pizza让python打开文件pizza.py,并把其中的所有函数都复制到这个程序里,开发者看不到复制的代码,只是在程序运行时,python在幕后复制这些代码。这样在文件making.py中,可以使用pizza.py中定义的所有函数。
在全面的代码中,使用了被导入模块里的函数,在使用时指定了导入的模块的名称pizza和函数名make,并用点"."分隔他们。
2)只导入指定的函数
在python程序中,可以更具项目的需要,只导入模块文件中的特定函数,不会调用使用其他的函数
格式如下:

from pizza import make
make(16,'黄油','虾','芝士')#此时就不要pizza.make,会报错
make(12,'黄油')#此时就不要pizza.make,会报错

3)使用as指定函数别名
在python中,如果从外部模块文件导入的函数名称与现有程序里的名称发生冲突,或者函数名太长,可以使用关键字“as“指定简短而独一无二的别名。

from pizza import make as mk
mk(16,'黄油','虾','芝士')
mk(12,'黄油')

4)使用as指定模块别名

import pizza as pi
pi.make(16,'黄油','虾','芝士')
pi.make(12,'黄油')

5)导入所有函数
在python程序中,可以使用星号运算符" * "导入外部模块文件里所有函数,下面可以使用此运算符导入外部模块文件中所有函数的过程。

from pizza import *
make(16,'黄油','虾','芝士')
make(12,'黄油')

此方法无需使用句点表示法

38-内存地址

#引用:通俗理解就是程序中的数据在内存中的地址:简称内存地址
#底层:数据结构
#a 存储的是一个内存地址值,10的内存地址
a = 10
#b 存储的是什么(也是内存地址,a的内存地址,10的内存地址值)
b = a
#打印内存地址
print("a的内存地址为",id(a))
print("b的内存地址为",id(b))
#16进制的内存地址值
print("a的16进制内存地址为",hex(id(a)))
print("b的16进制内存地址为",hex(id(b)))

#可变类型和不可变类型
a = 20
print("a的内存地址为",id(a))
运行结果:
a的内存地址为 1882975632
b的内存地址为 1882975632
a的16进制内存地址为 0x703bed90
b的16进制内存地址为 0x703bed90
a的内存地址为 1882975952

39-可变类型和不可变类型

#可变类型:可以在原有的数据基础上对数据进行修改(增删改查)
#不可变类型:不能在原有基础上对数据进行修改
#可变类型“列表,集合,字典”,对数据进行修改后,内存地址不会改变
#不可变类型:字符串,数字,元组,不能在原有数据上对数据进行修改

---可变类型操作---
#列表
my_list = [1,5,6]
print(my_list,id(my_list))
运行结果:[1, 5, 6] 2240182121800
#改变:增减
my_list[0]=2
my_list.append(10)
del my_list[1]
print(my_list,id(my_list))
运行结果:
[1, 5, 6] 2175318324552
[2, 6, 10] 2175318324552

#字典
my_dict = {"name":"李四","age":19}
print(my_dict,id(my_dict))
my_dict["name"] = "王五"
print(my_dict,id(my_dict))
运行结果:
{'name': '李四', 'age': 19} 2445022098200
{'name': '王五', 'age': 19} 2445022098200

#集合
my_set = {5,10}
print(my_set,id(my_set))
my_set.add("666")
print(my_set,id(my_set))
运行结果:
{10, 5} 2061172782920
{10, '666', 5} 2061172782920
(可变类型)

---不可变类型操作---
my_str = "hello"
print(id(my_str))
my_str[0]="l"
print(id(my_str))
运行结果:
TypeError: 'str' object does not support item assignment

my_str = "hello"
print(id(my_str))
my_str ="haha"(不属于修改数据(重新赋值))
print(id(my_str))
运行结果:
1618955770320
1618955769704

#数字类型
my_num =5
print(id(my_num))
my_num =10
print(id(my_num))
运行结果:
1980034288
1980034448

#元组
my_tuple = (4,6)
print(id(my_tuple))
my_tuple[0] = 2
print(my_tuple)
运行结果:
TypeError: 'tuple' object does not support item assignment

#这不叫修改数据,而是重新赋值,重新赋值任何类型的内存地址都会改变
my_list = [10,20]
print(id(my_list))
my_list = [30,40]
print(id(my_list))
运行结果:
1182973654344
1182973654280

40-global的使用-扩展

#提示:文件不要起中文名字
#定义一个全局变量
g_num = 10
print("函数外:",id(g_num))
def modify():
    #定义了一个局部变量
    g_num =1
    print("函数内:",id(g_num))
modify()
print(g_num)
运行结果:
函数外: 1980034448
函数内: 1980034160
10

g_num = 10
print("函数外:",id(g_num))
def modify():
    #表示要修改全局变量
    global g_num
    #定义了一个局部变量
    g_num =1
    print("函数内:",id(g_num))
modify()
print(g_num)
运行结果:
函数外: 1980034448
函数内: 1980034160
1

#定义一个可变类型的全局变量
g_list = [3,5]
print("函数外",id(g_list))
def modify():
    #在原有列表上增减一个数据,内存地址没有发生改变,就不需要global
    #global g_list 内存地址不改变,加不加global是一样的效果
    g_list.append(4)
    print(id(g_list))
modify()
print(g_list)
运行结果: 
函数外 1870219146568
函数内 1870219146568
[3, 5, 4]

#定义一个可变类型的全局变量
g_list = [3,5]
print("函数外",id(g_list))
def modify():
     g_list = [1,1]
    print("函数内",id(g_list))
modify()
print(g_list)
运行结果:
函数外 2337230189896
函数内 2337230189832
[3, 5]

#定义一个可变类型的全局变量
g_list = [3,5]
print("函数外",id(g_list))
def modify():
     #加上glogal 表示内存地址要发生变化
    global g_list
    g_list = [1,1]
    print("函数内",id(g_list))
modify()
print(g_list)
运行结果:
函数外 1612535526728
函数内 1612535526664
[1, 1]

41-公共运算符

# + 运算符 可以完成列表,元组,字符串的拼接
my_str1 = "hello"
my_str2 = "world"
result = my_str1 + my_str2
print(result)
my_list1 = [1,3]
my_list2 = [2,4]
#列表
result = my_list1 + my_list2
print(result)
#元组
my_tuple1 = (1,5)
my_tuple2 = (2,4)
result = my_tuple1 + my_tuple2
print(result)
运行结果:
helloworld
[1, 3, 2, 4]
(1, 5, 2, 4)

#  *运算符 可以完成列表,元组,字符串的乘积
result = "-"*30
print(result)
result = "ab"*15
print(result)
result = (4,6)*5
print(result)
运行结果:
------------------------------
ababababababababababababababab
(4, 6, 4, 6, 4, 6, 4, 6, 4, 6)

42-函数文档说明:

"""
这是一个多行注释
"""
def sum_num(num1,num2):
    #一般情况程序员不去写文档说明
    #第三方公司完成
 	#只需在方法里打出多行注释的引号,自动生成标准函数文档说明
    """
    :param num1:第一个数字
    :param num2:第二个数字
    :return:返回值
    """
    return num1+num2

43-偏函数:通俗理解就是指函数的参数偏爱某个值,这种函数就叫做偏函数

#通俗理解就是指函数的参数偏爱某个值,这种函数就叫做偏函数
import functools
def show(num1,num2,num3=3):
    result = num1+num2+num3
    return result
result = show(1,2)
print(result)

#偏函数的简写方式(返回的函数就是偏函数)
newfunc = functools.partial(show,num2=5)
result = newfunc(1)
print(result)
运行结果:
6
9

#在内部函数使用偏函数
result = int("123")
print(result,type(result))
#利用偏函数对系统内置函数设置偏爱值,数据类型转换按照2进制方式转换
newfunc = functools.partial(int,base = 2)
result = newfunc("1011010")
print(result,type(result))
运行结果:
123 <class 'int'>
90 <class 'int'>

44-返回函数

在函数内部返回一个函数,返回的这个函数就是返回函数

#在函数内部返回一个函数,返回的这个函数就是返回函数
#函数嵌套
def show():
    def show1():
        print("今天天气很冷")
    return show1
#newfunc就是show1
new_func = show()
new_func()
运行结果:
今天天气很冷

def calc(operation):
	if operation == "+":
		def sum_num(num1,num2):
			result = num1+num2
			return result
		#返回函数不需要加()加()就等于调用函数
		return sum_num
	if operation == "-":
		def jp_num(num1,num2):
			return num1-num2
		return jp_num
new_func = calc("+")
#相当于调用sum_num
result = new_func(1,2)
print(result)
运行结果:
3

def jisuan(num1,num2):
	result1 = num1+num2
	result2 = num1 -num2
	return result1,result2
#多个返回值包装成了元祖
result = sum_num(2,2)
print(value)
运行结果:
(4,0)

45-高阶函数

#当一个函数的参数,可以接收另一个函数
#函数作为参数
#或者,还可以返回一个函数,那么这个函数就叫做高阶函数
#只有参数是函数的高阶函数
def sum(num1,num2):
	result = num1+num2
	return result
#高阶函数,可以接受参数为函数
def calc_num(new_func):
	#sum就是外部传来的函数
	result=new_func(2,2)
	print(result)
#调用clac_num函数(参数为sum的函数)
result = calc_num(sum)
print(result)
运行结果:
4
None

#高阶函数:还可以返回函数,既有参数是函数,又有返回值是函数
def text(new_func):
	#调用传入的外部函数
	new_func()
	#内部函数
	def inner():
		print("我是内部函数")
	return inner
def show_msg():
	print("今天天气很好")

#调用高阶函数
#newfunc就是text函数里面的inner
new_func = text(show_msg)
new_func()
运行结果:
今天天气很好
我是内部函数

46-闭包

#闭包:闭包本质上也是一个函数(高阶函数)
#在函数嵌套的前提下,内部函数使用了外部函数的参数或者变量
#并且把这个内部函数返回,那么返回的函数就叫做闭包
def show(msg):
   #外部的变量
   num = 10
   def inner():
      #打印外部的变量,msg外部的变量
      #既使用了外部函数的参数,又使用了外部函数的变量
      print(msg,num)
   #inner就是闭包
   return inner
#new_func就是inner,就是闭包
new_func = show("哈哈")
print(new_func)
new_func()

运行结果:
<function show.<locals>.inner at 0x00000256504E6730>
哈哈 10


#闭包的应用场景:可以根据参数生成不同的返回函数
#通过闭包生成不同函数
def hello(msg,count):
	result = msg *count
	return result
result = hello("B",10)
print(result)
运行结果:
BBBBBBBBBBB

def hello(msg, count):
    def return_msg():
        result = msg * count
        return result
    return return_msg
new_func1 = hello("A", 10)
new_func2 = hello("b", 10)
# 根据不同的参数返回不同的函数
print(new_func1, "--------------", new_func2)
value1 = new_func1()
print(value1)
value2 = new_func2()
print(value2)
运行结果:
<function hello.<locals>.return_msg at 0x000001D517046730> -------------- <function hello.<locals>.return_msg at 0x000001D5260D5F28>
AAAAAAAAAA
bbbbbbbbbb

47-简单装饰器

#装饰器:一些操作,文件
#装饰器:本质上也是一个函数,可以在原函数的功能进行扩展
#不改变原函数额定义和调用的操作
def show():
    print("AAA")
#在AAA前面加上-------(装饰器本质是一个闭包)
def decorator(new_func):
    #定义
    def inner():
        print("-----")
        #调用传进来的函数
        new_func()
    return inner
inner = decorator(show)
inner()
运行结果:
-----
AAA

#装饰器
def show():
    print("AAA")
#在AAA前面加上-------(装饰器本质是一个闭包)
def decorator(new_func):
    #定义
    def inner():
        print("-----")
        #调用传进来的函数
        new_func()
    return inner
show = decorator(show)
show()
运行结果:
-----
AAA

#装饰器:本质上就是一个函数,可以给原函数增加新的功能(不改变原函数的情况)
#装饰器函数
def decorator(new_func):
    def inner():
        print("+++")
        new_func()
        #注意返回函数要是函数的名字,如果加括号等于调用函数
    return inner
def show():
    print("BBB")
show = decorator(show)
show()
运行结果:
+++
BBB

def decorator(new_func):
    def inner():
        print("+++")
        #这里才是真正的调用show
        new_func()
        #注意返回函数要是函数的名字,如果加括号等于调用函数
    return inner
@decorator#语法糖 作用为show = decorator(show)
def show():
    print("BBB")

# show = decorator(show)
show()

48-装饰器修饰带有参数的函数

#定义一个装饰器
def decorator(func):
    def inner():
        print("计算结果如下:")
        func(1,5)
    return inner
#定义了一个带有参数的函数,装饰器修饰他
@decorator
def sum(num1,num2):
    result = num1+num2
    print(result)
sum()
运行结果:
计算结果如下:
6

#定义一个装饰器
def decorator(func):
    def inner(num1,num2):
        print("计算结果如下:")
        func(num1,num2)
    return inner
#定义了一个带有参数的函数,装饰器修饰他
@decorator
def sum(num1,num2):
    result = num1+num2
    print(result)
sum(1,5)
运行结果:
计算结果如下:
6

49-通用的装饰器

#通用的装饰器,可以修饰任意函数
#定义一个带有参数的函数(2个,3个)
#使用不定长参数方式
def decorator(func):
    def inner(*args,**kwargs):
        print("计算结果如下:")
        result = func(*args,**kwargs)
        return result
    return inner
@decorator
def sum1(num1,num2):
    result = num1+num2
    return result
result = sum1(1,2)
print(result)
@decorator
def sum2(num1,num2,num3):
    result = num1+num2+num3
    return result
result = sum2(1,2,4)
print(result)
运行结果:
计算结果如下:
3
计算结果如下:
7

50-带有参数的装饰器

#定义一个带有参数的装饰器
#get函数的目的就是返回一个装饰器函数
def get_decorator(char):
    def decorator(func):
        def inner():
            print(char)
            func()
        return inner
    return decorator

@get_decorator("aaa")
def show():
    print("11111")
show()
运行结果:
aaa
11111

51-if判断的扩充

#if:bool类型,数字类型
if False:
    print("条件不成立")-----不执行
#数字类型:非0即真(只要不是0就满足条件)
if 0:
    print("条件不成立")-----不执行

#if 容器类型(字符串,列表,元组,字典,集合,二进制数据)
#容器类型判断的时候,如果容器类型里面有数据那么表示条件成立,
#否则条件不成立
if "xx":
    print("哈哈")
if [1,2]:
    print("呵呵")
if "":
    print("条件不成立")-----不执行
if {"name":"茹茹"}:
    print("在上课呢")
#非None条件成立
if None:
    print("......")
if not None:
    print(".....")

你可能感兴趣的:(python学习笔记--3.函数)