4.Python基础学习笔记day04-函数

4.Python基础学习笔记day04-函数

一、函数概述
'''
函数:
在项目开发的过程中,有些功能代码我们可能会经常使用,我们可以将这些代码按照它的功能
封装成函数,在需要的时候调用即可。
优点:
1.提高代码的复用性,简化代码结构
2.增加代码的可维护性
'''

'''
函数的定义:
def 函数名(参数列表):
    函数体
    return 表达式

def 关键字标识定义函数的开始
函数名 遵循标识符的命名规则
() 列表参数的开始以及结束,无论是否存在参数,小括号都不能省略
参数列表  参数与参数之间使用逗号隔开,若不存在参数可不写
: 函数的功能以冒号开始,并且需要缩进
函数体:封装的函数的功能
return 函数结束之后的返回值,若没有返回值return可以不写,不写的时候默认return None.
'''

def myprint():
    for x in range(5):
        print("you are a good  man")


'''
需求:按照传递的num来决定打印的条数
'''
def myprint2(n):
    for x in range(n):
        print("you are a good  man")


myprint2(9)
二、函数参数
'''
形参:形式参数
定义在函数的参数列表中的参数,我们称之为形参。
作用:用来接收函数的调用者传递过来值。
实参:实际参数
函数调用的过程中传递的参数
作用:给形参赋值
参数传递的本质:实参给形参赋值的过程。

对于不可变类型的传递是值传递
对于可变类型的传递是地址传递【引用传递】
若传递进去的对象是不可变类型,当在函数体内对象发生改变的时候,不会改变被传递的变量
若传递进去的变量是可变类型,当在函数内对该变量进行更改的时候,会影响到被传递的变量
'''
# 值传递
str1 = "hello world"
def func1(x):
    print(id(x))
    x = "abc"
    print(x)

print(str1)  # hello world
print(id(str1))  # 39007216
func1(str1)  # 39007216  abc
print(str1)  # hello world   --未改变

# 引用传递
list1 = [1,2,3,4]
def func2(x):
    print(x)  # [1, 2, 3, 4]
    print(id(x))  # 41563144
    x[-1] = "change"
    print(x)  # [1, 2, 3, 'change']
    print(id(x))  # 41563144


print(list1)  # [1, 2, 3, 4]
print(id(list1))  # 41563144
func2(list1)
print(list1)  # [1, 2, 3, 'change']

'''
位置参数【又称必选参数】
传递参数的顺序与定义的顺序有关,必须按照定义的顺序来进行传递。
传递参数的个数与参数的个数必须保持一致。


关键字参数:
指函数调用的时候,可以通过"键-值"的形式来加以指定,
可以清除位置关系。

当出现位置参数与关键字参数的时候,需要将位置参数写在关键字参数前面

默认参数
定义函数的时候,我们可以给参数提供默认值,调用函数的时候可以传递此参数
可以不传,当传递此参数的时候,函数则使用传递的参数,若不传递则使用默认值。


优点:方便函数的调用
注意:
1.若默认参数与位置参数同时存在的时候,位置参数要写在默认参数的前面
2.给定默认参数的时候,默认参数需要指向不可变对象。
'''

def ins1(name,age):
    print("大家好我是%s,我今年%d岁"%(name,age))

# 位置参数
ins1("lili",18)  # 大家好我是lili,我今年18岁

# 关键字参数
ins1(age=20, name="zhangsan")  # 大家好我是zhangsan,我今年20岁

# 默认参数
def ins(name,age,address="江西"):
    print("大家好我是%s,我今年%d岁,我家乡在%s"%(name,age,address))

ins1("wangwu",18)  # 大家好我是wangwu,我今年18岁

'''
不定长参数:
定义函数的时候,我们不确定调用的时候到底会传递多少参数进来【可能传递1个也可能多个或者不传递】
此时我们可以使用不定长参数来解决【不定长参数又包括包裹位置参数与包裹关键字参数】

特点:能处理比声明时候更多的参数【传递多少参数,处理多少参数,不传递不处理】

不定长参数分为两种:

包裹位置参数:
使用:*变量名  一般用*args
功能:可以收集除了必选参数以外剩余的位置参数,按照元组来进行处理

包裹关键字参数:
使用:**变量名  一般用**kwargs
功能:收集除定义的变量的关键字参数之外,剩余关键字参数。
包裹关键字参数只处理剩余的关键字参数,收集作为字典来进行处理。

注意:当位置参数【必选参数】,默认参数,包裹位置参数,包裹关键字参数同时存在
的情况下,一般的顺序为:
位置参数,默认参数,包裹位置参数,包裹关键字参数
默认参数与包裹位置参数可以根据需求,位置可以调换
'''
def mySum(*args):
    print(type(args))  # 
    sum = 0
    for i in args:
        sum += i
    return sum

print(mySum(1, 2, 3, 4, 5, 6, 7))  # 28



def func2(**kwargs):
    print(kwargs)  # {'x': 1, 'y': 2, 'z': 3}
    print(type(kwargs))  # 

func2(x=1, y=2, z=3)

# 可传任意参数的函数
def func(*args,**kwargs):
    pass
三、匿名函数
'''
匿名函数:
定义:指的是一类无须定义标识符【函数名】的函数或者子程序。
在python中定义匿名函数使用lambda来进行定义。
语法:
lambda 参数列表: 表达式

特点:
1.lambda后面的跟的只是一个表达式,结构体比def的简单
2.参数列表可以有多个参数,参数与参数之间使用逗号隔开
3.无须写return,表达式的结果就是该表达式的返回值。
优点:
1.结构简单
2.匿名函数没有名字无须担心函数名的冲突。

匿名函数的调用:
将lambda表达式赋值给一个变量,通过调用变量来调用我们的匿名函数。
'''

func = lambda a, b: a if a>b else b
print(func)  #  at 0x0000000000423F28>
print(type(func))  # 
print(func(10,20))  # 20
四、zip函数
'''
zip函数
zip(iter1,iter2,...)
功能:打包,将可迭代对象中对应位置的元素进行打包,
长度取决于最短的那个,返回zipobj打包好的对象,以迭代器的方式返回

zip(*zipobj)
解包,将之前打包的元素进行解包处理,以迭代器方式返回。
'''

list1 = [1,2,3,4,5]
list2 = ["hello","good","nice","great","hi"]
list3 = ["hello2","good2","nice2","great2"]
zipobj = zip(list1,list2,list3)

print(next(zipobj))  # (1, 'hello', 'hello2')
print(list(zipobj))  # [(2, 'good', 'good2'), (3, 'nice', 'nice2'), (4, 'great', 'great2')]

obj = zip(*zipobj)
print(next(obj))  # (2, 3, 4)
五、装饰器
'''
装饰器:
在代码运行的期间动态的增加功能的方式我们称之为装饰器。
'''

'''
最简单的装饰器:

def outer(func):
    def inner():
        #增强的功能
        #在内函数中执行func函数
        return func()
    return inner

在装饰器中,分为外函数与内函数:
外函数(outer):
1.将被装饰的函数传递进来--》func
2.将装饰好的函数返回给调用者 --》inner
内函数:
1.添加动态增加的功能
2.执行被装饰的函数

内函数中return什么时候可以省略?
注意:当被装饰的函数没有返回值的时候,内函数的return可以省略,
若被装饰的函数中存在返回值,则内函数的return则不能省略。

@装饰器
def func():
    pass

@的功能:将被装饰的函数的函数名作为参数传递给外函数,将外函数返回的
替代版的函数赋值给原本的函数。
'''
def outer(func):
    def inner():
        print("*********")
        # print("*********")
        return func()
    return inner


@outer
def now():
    print("2019-6-13")
    return True

# 调用
print(now())
'''
*********
2019-6-13
True
'''


'''
有参数的情况下
def outer(func):
    def inner(参数列表):
        #添加增加的功能
        return func(参数列表)
    return inner

注意:
1.使用内函数来接收被装饰函数的参数
2.调用被装饰的函数的时候,需要将参数传递进去。
'''

def outer(func):
    def inner(age):
        if age>=0 and age<=160:
            func(age)
        else:
            print("年龄有误")
    return inner
'''
使用装饰器,给函数添加一个对年龄的限制:
年龄[0,160]
'''
@outer
def getAge(age):
    print("您的年龄为%d"%age)
    
getAge(-100)  # 年龄有误
getAge(100)  # 您的年龄为100
getAge(200)  # 年龄有误
六、偏函数
import functools
'''
偏函数:将函数的某些值给固定住,给你返回一个新的函数,这个函数就是偏函数的功能。
newfunc = functool.partial(func,参数)
要导入 functools库
'''

'''
需求:
将二进制的字符串转为十进制
'''
print(int("1010101",base=2))

def int2(str1,base=2):
    return int(str1,base)

int3 = functools.partial(int,base=2)

print(int3("1010101"))  # 85
print(int3("101001"))  # 41
print(int3("101010"))  # 42
七、变量作用域与global关键字
'''
变量的作用域:变量起作用的范围。
程序中变量并不是在任意的地方都能访问,访问范围取决于它在赋值的位置【定义的位置】

局部作用域:在函数中定义的变量,每当函数被调用的时候它都会产生一个新的作用域,
这个新的作用域我们称之为局部作用域,在局部作用域中定义的变量,我们称之为局部变量
局部变量起作用的范围就是当前所在的这个函数。

嵌套作用域:又称函数作用域

全局作用域:在模块中定义的变量,并且定义在函数体之外的变量,
他们产生的作用域叫做全局作用域,这个变量我们称之为全局变量。
全局变量作用的范围整个.py文件。

内置作用域:
系统内部定义的变量产生的作用域,叫做内置作用域。
起作用的范围,所有的.py文件。

搜索变量的优先级:
局部作用域>嵌套作用域>全局作用域>内置作用域,
当这几个作用域中都不存在的时候则报错。
'''


'''
注意:在局部作用域中,不能直接更改全局变量的值,若有需要在局部作用域中更改
全局变量,则需要在更改之前对此变量进行声明,使用关键字global进行声明,
声明之后变可更改。

注意:在python中,只有模块,类以及函数【def,lambda】这些才会引入新的作用域,
而其他的语句块比如:if/else,while/for,try/except这些语句块不会引入新的作用域
也就是说在这些语句中定义的变量,在外部仍然可以使用。
'''
num1 = 100

def func():
    global num1
    num1 = 200
    print(num1)


for x in range(10):
    pass

print(x)  # 9
func()  # 200
print(num1)  # 200
八、回调函数、返回函数、闭包与递归函数
'''
回调函数:将函数作为参数传递到另外一个函数中,
这个被传递进去,后来又被调用的函数,我们称之为回调函数。
'''
def wake1(time):
    print("在%s点,使用揪耳朵的方式叫醒。。。"%time)

def  wake2(time):
    print("在%s点,使用泼冷水的方式叫醒..."%time)

def wake_server(func,time):
    return func(time)


wake_server(wake1,"下午一点五十")  # 在下午一点五十点,使用揪耳朵的方式叫醒。。。


'''
返回函数:把函数作为返回值返回的时候,我们可以称这个函数为返回函数
'''
def lazy_sum(*args):
    def calc_sum():
        sum1 = 0
        for i in args:
            sum1 += i
        return sum1
    return calc_sum


print(lazy_sum(1,2,3,4,5)())  # 15


'''
闭包:在外函数的内部定义了一个内函数,内函数使用了外函数的临时变量,
外函数的返回值是内函数的引用【内函数的函数名】,这时候就构成了一个闭包。

一般情况下当函数执行完毕,函数中所有的东西都会被释放掉还给内存,这时候局部变量也会消失,
但是当外函数结束的时候,发现自己还有临时变量在内函数中还会使用,此时外函数会将自己的临时变量
绑定内函数,自己再结束。

函数中的变量在函数被调用的时候创建,在函数执行结束的时候被销毁。

装饰器一定是闭包,但是闭包不一定是装饰器。
'''

def outerfunc():
    list1 = []
    for x in range(10):
        def inner():
            return x
        list1.append(inner)
    return list1

list1 = outerfunc()
for f in list1:
    print(f())
    
# 9 9 9 9 9 9 9 9 9 9 


'''
函数在内部是可以调用其他函数的,当被调用的函数是函数自己本身的时候,我们称这个函数为递归函数。

使用递归函数的时候,一定要注意栈溢出的情况。
一般情况下不建议使用递归函数。
'''

'''
n! = 1x2x3x...xn
1.写出临界条件:1! = 1
2.找出这次跟上次的关系
3.假设函数可以使用,根据上一次的值,求出本次的结果
f(n) = f(n-1)xn
f(n-1) = f(n-2)x(n-1)
...
f(2) = f(1)*2
f(1) = 1
'''
def f(n):
    if n == 1:
        return 1
    else:
        return f(n-1)*n

九、os模块使用
import os
'''
os.getcwd()    current working directory
功能:获取当前文件所在目录绝对路径

os.listdir(path)
功能:获取指定目录下所有文件的文件名,若不指定path则获取当前目录下的。

os.path.abspath(path)
功能:获取path的绝对路径【将path与当前文件所在目录的路径进行拼接处理】


os.path.split(path)
功能:将路径分解为目录与文件的部分,以元组的方式返回。
【实际上使用"/"对路径进行切分,从右往左切,切一次,左边获取到的就是目录部分,右边就是文件部分】

os.path.join(path,paths)
功能:对path进行路径拼接,若在paths中出现绝对路径,则前面的路径不保留,返回的后面的绝对路径。

os.path.dirname(path)
功能:返回path中目录的部分。

os.path.basename(path)
功能:返回path中文件的部分

os.path.getsize(path4)
功能:获取指定路径文件的大小,目录的大小获取不到。


os.path.exists(path)
功能:判断指定的路径是否存在,若存在则返回True,否则返回False

os.path.isdir(path)
功能:判断指定的路径是否为目录,若是则返回True,否则返回False

os.path.isfile(path)
功能:判断指定的路径是否为文件,若是则返回True,否则返回False
'''


'''
os.remove(path)
功能:删除指定的文件

os.mkdir(path)
功能:创建指定的目录

os.rmdir(path)
功能:删除指定的空目录【只能删除一层】

os.removedirs(path)
功能:递归删除多层空目录【不存在文件】

os.makedirs(path)
功能:递归创建多层空目录

os.chdir(path)
功能:切换到指定的目录
'''

你可能感兴趣的:(Python,python)