Python定义参数数量可变的method的问题

本文详细介绍了Python中定义函数的三种方法:默认参数值、任意参数列表及关键字参数,并通过实例展示了如何使用这些特性来增强函数的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

根据文档(https://docs.python.org/2/tutorial/controlflow.html#more-on-defining-functions)

介绍了三种方法

1 Default Argument Values 

The most useful form is to specify a default value for one or more arguments. This creates a function that can be called with fewer arguments than it is defined to allow

比较简单,就是给每个method中的参数赋一个默认值

The default values are evaluated(赋值) at the point of function definition in the defining scope, so that

i = 5

def f(arg=i):
    print arg

i = 6
f()

will print 5.

Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes. For example, the following function accumulates the arguments passed to it on subsequent calls:

def f(a, L=[]):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)

this will print:

[1]
[1, 2]
[1, 2, 3]

If you don’t want the default to be shared between subsequent calls, you can write the function like this instead:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

 

2 Arbitrary Argument Lists

使用*args的时候,将传入的参数pack成tuple来处理:

def foo(*args):
  for a in args:
    print a
  print 'end of call'

lst = [1,2,3]
foo(lst)    
foo(*lst)

#output:
[1, 2, 3]
end of call
1
2
3
end of call

 

3 Keyword Arguments

使用**kw的时候,将传入的所有的keyword arguments来pack成dict处理:

When a final formal parameter of the form **name is present, it receives a dictionary (see Mapping Types — dict) containing all keyword arguments except for those corresponding to a formal parameter.

对这句话的解释:

def bar(name='Jack', age=21, **kw):
  print kw

bar(a=1, b=2)  # {'a': 1, 'b': 2}
bar(name='Lucy', job='doctor') # {'job': 'doctor'}

 

stackoverflow(https://stackoverflow.com/questions/33542959/why-use-packed-args-kwargs-instead-of-passing-list-dict)总结的*,**的适用场景 :

*args/**kwargs has its advantages, generally in cases where you want to be able to pass in an unpacked data structure, while retaining the ability to work with packed ones.

Of course, if you expect the function to always be passed multiple arguments contained within a data structure, as sum() and str.join() do, it might make more sense to leave out the *syntax.

 

关于 Unpacking Argument Lists的解释:

The reverse situation occurs when the arguments are already in a list or tuple but need to be unpacked for a function call requiring separate positional arguments.

举例:

>>> range(3, 6)             # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args)            # call with arguments unpacked from a list
[3, 4, 5]

In the same fashion, dictionaries can deliver keyword arguments with the **-operator:

>>> def parrot(voltage, state='a stiff', action='voom'):
...     print "-- This parrot wouldn't", action,
...     print "if you put", voltage, "volts through it.",
...     print "E's", state, "!"
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !

 

 

 

转载于:https://www.cnblogs.com/geeklove01/p/9122303.html

<think>根据用户的问题,用户想知道如何在Python的类中接收和处理可变参数。结合用户提供的引用,特别是引用[2]和引用[4],我们可以知道Python中的可变参数包括位置可变参数(*args)和关键字可变参数(**kwargs)。这些不仅可以在函数中使用,也可以在类的方法中使用。 在类中,我们通常在`__init__`方法或其他方法中使用可变参数,以便在创建实例或调用方法可以传入任意数量参数。 下面我将详细解释并给出示例: ### 1. 在类方法中使用位置可变参数(*args) 位置可变参数允许我们在调用方法传入任意数量的位置参数。这些参数会被收集到一个元组(tuple)中。 ### 2. 在类方法中使用关键字可变参数(**kwargs) 关键字可变参数允许我们传入任意数量的关键字参数,这些参数会被收集到一个字典(dict)中。 ### 示例代码 下面我们创建一个类`Example`,在它的`__init__`方法中使用`*args`和`**kwargs`,同我们也会创建一个使用可变参数的实例方法。 ```python class Example: def __init__(self, *args, **kwargs): # 位置参数保存在元组args中 self.args = args # 关键字参数保存在字典kwargs中 self.kwargs = kwargs def print_args(self): print("位置参数:", self.args) print("关键字参数:", self.kwargs) def dynamic_method(self, *args, **kwargs): print("动态方法接收的位置参数:", args) print("动态方法接收的关键字参数:", kwargs) # 创建实例,传入位置参数和关键字参数 example = Example(1, 2, 3, name='Alice', age=30) # 调用实例方法 example.print_args() # 输出: # 位置参数: (1, 2, 3) # 关键字参数: {'name': 'Alice', 'age': 30} # 调用动态方法,传入可变参数 example.dynamic_method('a', 'b', 'c', city='New York', country='USA') # 输出: # 动态方法接收的位置参数: ('a', 'b', 'c') # 动态方法接收的关键字参数: {'city': 'New York', 'country': 'USA'} ``` ### 说明: - 在`__init__`方法中,我们使用`*args`来接收任意数量的位置参数,使用`**kwargs`来接收任意数量的关键字参数。这样,在创建实例,我们可以传入任意数量参数。 - 我们将传入的位置参数和关键字参数分别保存为实例属性,以便在其他方法中使用。 - 类中的其他方法(如`dynamic_method`)也可以使用`*args`和`**kwargs`来接收可变参数。 ### 注意事项: 1. 在定义方法,`*args`必须放在`**kwargs`之前。 2. 如果同有必选参数、默认参数可变位置参数可变关键字参数,顺序应该是:必选参数、默认参数、`*args`、`**kwargs`。 3. 在调用方法,位置参数必须在关键字参数之前。 ### 应用场景: - 当我们需要设计一个可以接收任意参数的类(比如基类),使用可变参数可以增加灵活性。 - 在子类化过程中,如果我们需要将额外的参数传递给父类的初始化方法,可以使用`*args`和`**kwargs`。 ### 示例:子类中使用可变参数 ```python class Parent: def __init__(self, name, *args, **kwargs): self.name = name self.args = args self.kwargs = kwargs class Child(Parent): def __init__(self, age, *args, **kwargs): # 将args和kwargs传递给父类的初始化方法 super().__init__(*args, **kwargs) self.age = age child = Child(age=10, name='Bob', city='Shanghai') print(child.name) # 输出: Bob print(child.age) # 输出: 10 print(child.kwargs) # 输出: {'city': 'Shanghai'} ``` 在上面的例子中,创建`Child`实例,我们传入了`age`、`name`和`city`。其中`name`和`city`通过`*args`和`**kwargs`传递给了父类`Parent`的初始化方法。 通过以上示例,我们可以看到在类中使用可变参数的方法和函数中类似,但要注意在类的方法中的参数传递顺序。 §§相关问题§§ 1. Python可变参数(*args)和关键字参数(**kwargs)有什么区别? 2. 在类的方法中同使用位置参数、默认参数可变参数和关键字参数,顺序应该如何排列? 3. 如何将子类的可变参数传递给父类的初始化方法? 4. 使用可变参数有哪些常见的错误需要避免?</think>### Python 类中接收和处理可变参数的方法 在 Python 类中,可以通过两种方式接收可变参数: 1. **位置可变参数**:使用 `*args` 接收任意数量的位置参数 2. **关键字可变参数**:使用 `**kwargs` 接收任意数量的关键字参数 #### 基础实现示例 ```python class FlexibleClass: def __init__(self, *args, **kwargs): """初始化方法接收可变参数""" self.args = args # 位置参数保存为元组 self.kwargs = kwargs # 关键字参数保存为字典 def display(self): print("位置参数:", self.args) print("关键字参数:", self.kwargs) # 创建实例 obj = FlexibleClass(1, 2, 3, name="Alice", city="Beijing") obj.display() ``` **输出**: ``` 位置参数: (1, 2, 3) 关键字参数: {'name': 'Alice', 'city': 'Beijing'} ``` #### 高级应用场景 1. **继承中的参数传递** ```python class Base: def __init__(self, base_param, *args, **kwargs): self.base_param = base_param super().__init__(*args, **kwargs) # 传递给下一个父类 class Child(Base): def __init__(self, child_param, *args, **kwargs): self.child_param = child_param super().__init__(*args, **kwargs) # 传递给父类 obj = Child(child_param="子类", base_param="父类", extra="额外参数") print(f"子类参数: {obj.child_param}, 父类参数: {obj.base_param}") ``` 2. **动态方法参数** ```python class Processor: def process(self, *args): return sum(args) # 处理任意数量的数值参数 def configure(self, **options): self.settings = options # 存储配置选项 p = Processor() p.configure(precision=2, mode="fast") result = p.process(10, 20, 30) # 输出 60 ``` #### 关键注意事项 1. **参数顺序规则**(必须遵守): ```python def method(self, required, optional=0, *args, **kwargs): ``` - 必选参数 → 可选参数 → `*args` → `**kwargs` 2. **参数解包**: ```python params = (1, 2, 3) options = {"color": "red", "size": 10} obj = FlexibleClass(*params, **options) ``` 3. **类型检查**(推荐): ```python def __init__(self, *args, **kwargs): if not all(isinstance(x, int) for x in args): raise TypeError("位置参数必须是整数") ``` #### 实际应用场景 - 创建可扩展的基类 - 实现装饰器类 - 构建配置灵活的组件 - 处理不确定数量的输入数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值