从零开始学习人工智能Day4-Python3 函数

​​​​二、Python3基础语法学习

三、Python3 基本数据类型

四、Python3 数据类型转换

五、Python3 运算符

六、python基本数据类型(续)

七、Python3 控制语句

八、Python推导式

九、Python3 函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数

1.定义一个函数

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数
  • 函数内容以冒号 : 起始,并且缩进
  • return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。

语法 :

def 函数名(参数列表):
    函数体

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

def hello(name):
    print("Hello, ", name)

name='Alice'
hello(name) #输出Hello, Alice

2.函数调用

def add(x,y):
    return x+y

print(add(2,3)) #输出5

3.参数传递 

在 python 中,类型属于对象,对象有不同类型的区分,变量是没有类型的。

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

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

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

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

python 函数的参数传递

  • 不可变类型:类似 C++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。

  • 可变类型:类似 C++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响

3.2 python 传不可变对象实例

def change(x):
    print(id(x))    #输出 1927008682352
    print(x)        #输出 5

    x=10             #修改变量x的值

    print(id(x))    #输出 1927008682512
    print(x)        #输出 10

x=5
print(id(x))       #输出 1927008682352
print(x)           #输出 5

change(x)          #修改变量x的值,不可变对象的改变不会影响到函数外的变量

print(id(x))       #输出 1927008682352
print(x)           #输出 5

3.3 传可变对象实例

def change_list(lst):
    print(id(lst))   #输出 1927008682352
    print(lst)       #输出 [5, 6, 7]
    
    lst.append(10)   #修改列表的值

    print(id(lst))   #输出 1927008682352
    print(lst)       #输出 [5, 6, 7, 10]

lst=[5,6,7]
print(id(lst))      #输出 1927008682352
print(lst)          #输出 [5, 6, 7]

change_list(lst)    #修改列表的值,可变对象的改变会影响到函数外的变量,因为函数内的变量是引用类型,指向同一块内存地址

print(id(lst))      #输出 1927008682352
print(lst)          #输出 [5, 6, 7, 10]

4.参数

以下是调用函数时可使用的正式参数类型:

  • 必需参数
  • 关键字参数
  • 默认参数
  • 不定长参数

4.1 必需参数

必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

def func(str):
    print(str)

func()  #输出:TypeError: func() missing 1 required positional argument: 'str'

4.2 关键字参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值

def func(name, age):
    print(name, age)

func(age=20, name='Alice')  #输出:Alice 20

4.3 默认参数

如果没有传递参数,则会使用默认参数。

def func(name, age=20):
    print(name, age)

func(name='Alice')  #输出:Alice 20

4.4 不定长参数

你可能需要一个函数能处理比当初声明更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明不会命名。基本语法如下:

def functionname([formal_args,] *var_args_tuple ):
   "函数_文档字符串"
   function_suite
   return [expression]

 加了星号 * 的参数会以元组(tuple)的形式导入存放所有未命名变量参数

#不定长参数
def func(*args):
    print(args)
    print(type(args))    #输出:<class 'tuple'>

func(1, 2, 3)  #输出:(1, 2, 3)

还有一种就是参数带两个星号 **基本语法如下:

def functionname([formal_args,] **var_args_dict ):
   "函数_文档字符串"
   function_suite
   return [expression]

加了两个星号 ** 的参数会以字典的形式导入。 

def func(**dic):
    print(dic)
    print(type(dic))    #输出:<class 'dict'>

func(name='Alice', age=20)  #输出:{'name': 'Alice', 'age': 20}    

注意:声明函数时,参数中星号 * 可以单独出现,如果单独出现星号 *,则星号 * 后的参数必须用关键字传入

def func(a,b,*,c):
    print(a,b,c)

func(1,2,c=3)  #输出:1 2 3
# func(1,2,3)    #输出:TypeError: func() takes 2 positional arguments but 3 were given

5.匿名函数

Python 使用 lambda 来创建匿名函数

所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

lambda 函数特点:

  • lambda 函数是匿名的,它们没有函数名称,只能通过赋值给变量或作为参数传递给其他函数来使用。
  • lambda 函数通常只包含一行代码,这使得它们适用于编写简单的函数。

语法:

lambda arguments: expression

  • lambda是 Python 的关键字,用于定义 lambda 函数。
  • arguments 是参数列表,可以包含零个或多个参数,但必须在冒号(:)前指定。
  • expression 是一个表达式,用于计算并返回函数的结果。

add = lambda x,y:x+y
print(add(2,3))  #输出:5

将匿名函数封装在一个函数内,这样可以使用同样的代码来创建多个匿名函数

def multipul(x):
    return lambda y:x*y

doubler = multipul(2)
tripler = multipul(3)

print(doubler(3))  #输出:6
print(tripler(3))  #输出:9

6.return 语句

return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None

def add(x,y):
    total= x+y
    return total

total=add(2,3)
print(total)  #输出:5

7.强制位置参数

Python3.8 新增了一个函数形参语法 / 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。

def func(a,b,/,c,*,d):
    #形参 a 和 b 必须使用指定位置参数,c可以是位置形参或关键字形参,而d要求为关键字形参:
    print(a,b,c,d)

#func(1,b=2,3,d=4)#SyntaxError: positional argument follows keyword argument
func(1,2,3,d=4)  #输出:1 2 3 4

8.Python 装饰器

装饰器(decorators)是 Python 中的一种高级功能,它允许你动态修改函数或类的行为。

装饰器是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。

装饰器的语法使用 @decorator_name 来应用在函数或方法上。

Python 还提供了一些内置的装饰器,比如 @staticmethod 和 @classmethod,用于定义静态方法和类方法

装饰器的应用场景:

  • 日志记录: 装饰器可用于记录函数的调用信息参数返回值
  • 性能分析: 可以使用装饰器来测量函数执行时间
  • 权限控制: 装饰器可用于限制对某些函数的访问权限
  • 缓存: 装饰器可用于实现函数结果的缓存,以提高性能。

8.1 基本语法

Python 装饰允许在不修改原有函数代码的基础上,动态增加或修改函数的功能,装饰器本质上是一个接收函数作为输入并返回一个的包装过后的函数的对象

def decorator_function(original_function):
    def wrapper(*args, **kwargs):
        # 这里是在调用原始函数前添加的新功能
        before_call_code()
        
        result = original_function(*args, **kwargs)
        
        # 这里是在调用原始函数后添加的新功能
        after_call_code()
        
        return result
    return wrapper

# 使用装饰器
@decorator_function
def target_function(arg1, arg2):
    pass  # 原始函数的实现

解析:decorator 是一个装饰器函数,它接受一个函数 func 作为参数,并返回一个内部函数 wrapper,在 wrapper 函数内部,你可以执行一些额外的操作,然后调用原始函数 func,并返回其结果。

  • decorator_function 是装饰器,它接收一个函数 original_function 作为参数
  • wrapper 是内部函数,它是实际会被调用的新函数,它包裹了原始函数的调用,并在其前后增加了额外的行为。
  • 当我们使用 @decorator_function 前缀在 target_function 定义前,Python会自动将 target_function 作为参数传递给 decorator_function,然后将返回的 wrapper 函数替换掉原来的 target_function

8.2 使用装饰器

装饰器通过 @ 符号应用在函数定义之前,

@time_logger
def target_function():
    pass

等同于: 

def target_function():
    pass
target_function = time_logger(target_function)

target_function 函数传递给 decorator 装饰器,并将返回的函数重新赋值给 target_function。从而,每次调用 target_function 时,实际上是调用了经过装饰器处理后的函数。 

def my_decorator(func):
    def wrapper():
        print("原函数执行之前")
        func()
        print("原函数执行之后")
    return wrapper

@my_decorator
def hello():
    print("Hello, world!")

hello() 
#输出:
# 原函数执行之前 
# Hello, world! 
# 原函数执行之后
  • my_decorator 是一个装饰器函数,它接受hello() 作为参数,并返回 wrapper 函数。
  • @my_decorator 将hello() 替换为 wrapper(实际上执行的函数)。

8.3 带参数的装饰器

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("原函数执行之前")
        func(*args, **kwargs)
        print("原函数执行之后")
    return wrapper

@my_decorator
def hello(name):
    print(f"Hello,{name}")

hello("Alice")
#输出:
# 原函数执行之前
# Hello, Alice
# 原函数执行之后

装饰器本身也可以接受参数,此时需要额外定义一个外层函数

def repeat(num):
    def my_decorator(func):
        def wrapper(*args,**kwargs):
            print("原函数执行之前")
            for i in range(num):
                func(*args,**kwargs)
            print("原函数执行之后")
        return wrapper  #返回装饰器函数
    return my_decorator #返回装饰器函数,必须要有返回值函数

@repeat(3)
def hello(name):
    print(f"Hello,{name}")

hello("Alice")
#输出:
# 原函数执行之前
# Hello,Alice
# Hello,Alice
# Hello,Alice
# 原函数执行之后

8.4 类装饰器

类装饰器是包含 __call__ 方法的类,它接受一个函数作为参数,并返回一个新的函数。

def class_decorator(cls):    #定义装饰器函数,接收原始类 cls 作为参数。

    class Wrapper: 
    #在装饰器函数内部定义了一个新的类 Wrapper。这个类将用于包裹原始类 cls,并添加额外的功能。

        def __init__(self, *args, **kwargs):    
        #在 Wrapper 类的构造函数中,接收原始类的构造函数所需的参数。
            
            self.wrapper = cls(*args, **kwargs)
            #创建了原始类 cls 的一个实例,并将其存储在 self.wrapper 中。
            #这样,Wrapper 类就可以通过 self.wrapper 来访问和操作原始类的实例。
        
        def display(self):       
        #在 Wrapper 类中添加一个 display 方法,用于显示原始类的信息。

            print("原函数执行之前")    
            self.wrapper.display()    #调用原始类的 display 方法。
            print("原函数执行之后")

    return Wrapper

@class_decorator
class MyClass:
    def __init__(self, name):
        self.name = name
    def display(self):
        print(f"Hello,{self.name}")

obj = MyClass("Alice")
obj.display()
#输出:
# 原函数执行之前
# Hello,Alice
# 原函数执行之后

8.5 内置装饰器

Python 提供了一些内置的装饰器,例如:

  1. @staticmethod: 将方法定义为静态方法,不需要实例化类即可调用。

  2. @classmethod: 将方法定义为类方法,第一个参数是类本身(通常命名为 cls)。

  3. @property: 将方法转换为属性,使其可以像属性一样访问。

class MyClass:
    @staticmethod
    def static_method():
        print("静态方法")

    @classmethod
    def class_method(cls):
        print("类方法")

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

obj = MyClass()
obj.static_method()  #输出:静态方法
obj.class_method()   #输出:类方法
obj.name = "Alice"
print(obj.name)      #输出:Alice

8.6 多个装饰器的堆叠

你可以将多个装饰器堆叠在一起,它们会按照从下到上的顺序依次应用。

def decorator1(func):
    def wrapper():
        print("decorator1")
        func()
    return wrapper

def decorator2(func):
    def wrapper():
        print("decorator2")
        func()
    return wrapper

@decorator1
@decorator2
def hello():
    print("Hello, world!")

hello()
#输出:
# decorator1
# decorator2
# Hello, world!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值