【Python】Python参数详解

【Python】Python参数详解

目录

Python参数种类

Python参数定义

不定参数接收

限定传入参数方式

具体示例

位置参数示例

关键词参数示例

两种方法都支持的形式

参数默认值(可选参数)

参数默认值定义

引用类型默认值异常行为

参数类型声明

参数类型定义申明

函数返回值类型声明

参数与装饰器

Python参数种类

总体来看,Python支持两种类型的方法参数,其类型分别为:

位置参数(Positional Parameters)关键词参数(Keyword Parameters)

然后我们看下参数的传递形式,假如有如下函数定义:

def f(a,b,c):

...

如果我们通过如下方式调用,则称为位置参数:

f(1,2,3)

# 这里的 1,2,3 分别对应位置 a,b,c ,故这里是位置参数

args=[1,2,3]

f(*args)

如果我们通过如下方式调用,则称为关键词参数。这种方式下,我们不用关心参数位置,而是使用显示指定的方式指定每个参数的值,相比之下,这种方式更明确每个参数的值。

f(b=2,c=3,a=1)

# 或者

kwargs = {"b":2,"c":3,"a":1}

f(**kwargs)

⚠️当我们在给定参数时候,关键词参数后,不可跟位置参数,即如下调用方式是错误的

>>> f(2,b=3,1)

SyntaxError: positional argument follows keyword argument

Python参数定义

不定参数接收

最常见的形式:

def f(*args,**kwargs):

...

其中,args用于接收位置参数,即args类型是列表;kwargs用于接收keyword参数,即kwargs是一个字典。

限定传入参数方式

从官方给的这个示例说起

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):

----------- ---------- ----------

| | |

| 位置参数/关键词参数 |

| - 只能关键词参数

-- 只能是位置参数

根据上述示例,不难看出,在方法定义的时候,我们可以通过特定的两个符号/和*将参数分开。即/前面的只能是未知参数,/与* 之间的参数即可使位置参数,也可以是关键词参数,*后面的参数必须是关键词参数。

考虑到不定参数同时存在的情况,支持如下定义形式

def f(a,/,b,c,*args,**kwargs):

...

# 或

def f(a,/,b,c,*args):

...

# 或

def f(a,/,b,c,**kwargs):

...

# 或

ef f(a,/,b,c,*,d,**kwargs):

...

具体示例

位置参数示例

方法定义:

def f(pos1,pos2,/):

...

正确调用方式

f(1,2)

错误调用方式及其报错

>>> f(1,pos2=2)

TypeError: f() got some positional-only arguments passed as keyword arguments: 'pos2'

>>> f(pos1=1,pos2=2)

TypeError: f() got some positional-only arguments passed as keyword arguments: 'pos1, pos2'

关键词参数示例

方法定义

def f(*,pos1,pos2):

...

正确调用方式

>>> f(pos1=1,pos2=2)

错误调用方式及其异常

>>> f(1,2)

TypeError: f() takes 0 positional arguments but 2 were given

>>> f(1,pos2=2)

TypeError: f() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given

两种方法都支持的形式

方法定义

def f(a,/,pos1,pos2,*,b):

...

⚠️ 如下方式定义会抛出异常

>>> def f(/,pos1,pos2,*):

...

SyntaxError: invalid syntax

# / 前面必须有参数, * 后面必须有参数

正确调用方式

>>> f(1,2,3,b=4)

>>> f(1,2,pos2=3,b=4)

参数默认值(可选参数)

Python中,给定默认值的参数都是可选参数。

参数默认值定义

Python函数定义的时候,按照参数顺序,从第一个给定默认值之后的参数之后,必须提供默认值

def f(a=1,b=2,c=None):

...

异常定义及其错误

>>> def f(a,b=2,c):

...

def f(a,b=2,c):

^

SyntaxError: non-default argument follows default argument

引用类型默认值异常行为

有的时候,你可能需传入一个默认的列表,如

def f(a:list=[]):

a.append(1)

return a

当我们如下操作,会发现第二次的输出并不是我们希望的

f() # 输出 [1]

f() # 输出 [1, 1]

正确应该采用如下方式定义

def f(a: list = None):

if a is None:

a = []

a.append(1)

return a

# 字典参数的情况

def f(a: dict = None):

if a is None:

a = {}

参数类型声明

Python是动态类型语言,其变量的类型在运行时才确定。虽然这种灵活性为开发者带来了方便,但也可能导致代码在运行时发生类型错误。为了提高代码的可维护性和可读性,Python 3.5及以上版本引入了类型提示(Type Hints)。

参数类型定义申明

在函数定义时,可以使用冒号**:**来指定参数的类型

def greet(name: str):

return "Hello, " + name

函数返回值类型声明

我们可以使用**->**符号来指定函数的返回值类型。例如

def add(x: int, y: int) -> int:

return x + y

其他类型参数声明参考typing库。

参数与装饰器

首先,我们定义了一系列实用的装饰器,用于测量函数的执行时间。接着,我们定义了几个简单的函数,其中包括不同类型的参数和使用了不同装饰器的函数。

import inspect

from functools import wraps

def timeit(func):

import time

@wraps(func)

def wrapper(*args, **kwargs):

start = time.time()

func(*args, **kwargs)

print(f"cost time: {time.time() - start}")

return wrapper

def timeit1(name):

def _timeit(func):

import time

@wraps(func)

def wrapper(*args, **kwargs):

start = time.time()

func(*args, **kwargs)

print(f"{name} cost time: {time.time() - start}")

return wrapper

return _timeit

def timeit2(name):

def _timeit(func):

import time

@wraps(func)

def wrapper(param1, param2, param3):

start = time.time()

func(param1, param2, param3)

print(f"{name} cost time: {time.time() - start}")

return wrapper

return _timeit

def func1(param1, param2, param3):

print(param1, param2, param3)

@timeit

def func2(param1, param2, param3):

print(param1, param2, param3)

@timeit1("func3")

def func3(param1, param2, param3):

print(param1, param2, param3)

@timeit2("func4")

def func4(param1, param2, param3):

print(param1, param2, param3)

def call_func(func):

arg_spect = inspect.getfullargspec(func)

print(f"arg_spect: {arg_spect}")

...

>>> call_func(func1)

arg_spect: FullArgSpec(args=['param1', 'param2', 'param3'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})

--------------------

>>> call_func(func2)

arg_spect: FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})

--------------------

>>> call_func(func3)

arg_spect: FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})

--------------------

>>> call_func(func4)

arg_spect: FullArgSpec(args=['param1', 'param2', 'param3'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})

--------------------

通过上述结果,我们可以看到不同类型的函数具有不同的参数信息。对于普通的函数,我们可以通过 inspect.getfullargspec 来获取其参数信息。而对于使用了装饰器的函数,装饰器的实现方式会影响inspect.getfullargspec方法获取实际的参数信息。

相关推荐

冬天用什么护肤品好? 男生用什么护肤品好?
365bet在线官网

冬天用什么护肤品好? 男生用什么护肤品好?

📅 07-21 👁️ 287
App保持登录状态的常用方法
365bet在线官网

App保持登录状态的常用方法

📅 07-10 👁️ 6234
JPG转换器
365bet在线官网

JPG转换器

📅 07-05 👁️ 5487
冒菜为什么叫冒菜?
天天365彩票软件官方下载3D

冒菜为什么叫冒菜?

📅 07-04 👁️ 4322
住房朝向全解析客厅、主卧风水及各功能区朝向选择
如何在缺氧游戏中高效获得缺氧藻类?详细步骤及方法介绍
天天365彩票软件官方下载3D

如何在缺氧游戏中高效获得缺氧藻类?详细步骤及方法介绍

📅 08-27 👁️ 206