Python 中的默认值是什么?
在编写 Python 代码时,我们经常会使用函数和变量。而在定义函数和变量时,我们也经常需要提供参数的默认值。那么,在 Python 中,当我们没有为参数提供任何值时,它们的默认值是什么呢?本文将为大家详细介绍 Python 中的默认值。
阅读更多:Python 教程
函数中的默认值
在 Python 中,当我们定义一个函数时,可以为函数的参数提供默认值。例如:
def print_hello(name='world'):
print('Hello, ' + name + '!')
在上面的代码中,我们定义了一个名为 print_hello
的函数,该函数有一个名为 name
的参数,并为该参数提供了默认值 'world'
。如果在调用 print_hello
函数时不提供任何参数,那么将使用 'world'
作为参数的默认值。例如:
# 输出:Hello, world!
print_hello()
# 输出:Hello, Python!
print_hello('Python')
在上面的代码中,我们先调用 print_hello
函数时未提供任何参数,因此将使用 'world'
作为参数的默认值。接着,我们再次调用 print_hello
函数并将参数设置为 'Python'
,因此将输出 'Hello, Python!'
。
需要注意的是,当我们使用可变对象作为参数的默认值时,可能会出现奇怪的问题。例如:
def append_to_list(item, lst=[]):
lst.append(item)
print(lst)
在上面的代码中,我们定义了一个名为 append_to_list
的函数,该函数有两个参数,一个是要追加的元素,另一个是要追加到的列表。在函数定义中,我们为第二个参数 lst
提供了默认值 []
。然后,我们向 lst
列表中添加元素,并输出结果。
现在,让我们先调用 append_to_list
函数并向其传递一个元素 'a'
:
# 输出:['a']
append_to_list('a')
在上面的代码中,当我们调用 append_to_list
函数时,并没有向其传递第二个参数 lst
,因此将使用参数的默认值 []
。接着,我们将元素 'a'
添加到 lst
列表中,并输出结果。
现在,让我们再次调用 append_to_list
函数并向其传递一个元素 'b'
:
# 输出:['a', 'b']
append_to_list('b')
在上面的代码中,我们再次调用 append_to_list
函数,并向其传递一个元素 'b'
。然而,输出结果却不是我们所预期的 ['b']
,而是 ['a', 'b']
。这是因为,当我们使用可变对象(如列表、字典等)作为参数的默认值时,它们将被所有函数调用所共享,从而导致错误的行为。
如果我们希望避免这个问题,可以在函数内部创建一个新的列表,并将其作为参数的默认值。例如:
def append_to_list_v2(item, lst=None):
if lst is None:
lst = []
lst.append(item)
print(lst)
在上面的代码中,我们重新定义了一个名为 append_to_list_v2
的函数,并在该函数内部判断参数 lst
是否为 None
。如果 lst
为 None
,则创建一个新的空列表,并将其作为参数的默认值。然后,我们向 lst
列表中添加元素,并输出结果。
现在,让我们先调用 append_to_list_v2
函数并向其传递一个元素 'a'
:
# 输出:['a']
append_to_list_v2('a')
在上面的代码中,当我们调用 append_to_list_v2
函数时,并没有向其传递第二个参数 lst
,因此将使用参数的默认值 None
。接着,函数内部判断 lst
是否为 None
,发现它确实是 None
,因此创建一个新的空列表作为参数的默认值,并将元素 'a'
添加到该列表中。然后,输出结果 ['a']
。
现在,让我们再次调用 append_to_list_v2
函数并向其传递一个元素 'b'
:
# 输出:['b']
append_to_list_v2('b')
在上面的代码中,我们再次调用 append_to_list_v2
函数,并向其传递一个元素 'b'
。此时,函数内部发现参数 lst
已经不是 None
了,因此直接将元素 'b'
添加到 lst
列表中,并输出结果 ['b']
。这次,输出结果与我们所预期的一样了。
变量中的默认值
除了函数中的参数可以有默认值外,Python 中的变量也可以有默认值。例如:
name = 'world'
print('Hello, ' + name + '!')
在上面的代码中,我们定义了一个名为 name
的变量,并将其默认值设置为 'world'
。然后,我们将 'Hello, ' + name + '!'
打印到了屏幕上。因为 name
变量已经有了默认值,所以在打印时并没有给它赋值。
另外,Python 中的类也可以有默认值。在类定义中,我们可以使用 __init__
方法来为类的属性设置默认值。例如:
class Person:
def __init__(self, name='unknown', age=0):
self.name = name
self.age = age
person1 = Person()
person2 = Person('Alice', 23)
print(person1.name) # 输出:unknown
print(person1.age) # 输出:0
print(person2.name) # 输出:Alice
print(person2.age) # 输出:23
在上面的代码中,我们定义了一个名为 Person
的类,并为其 __init__
方法的两个参数 name
和 age
设置了默认值。然后,我们创建了两个 Person
类的实例,并分别输出了它们的属性值。
需要注意的是,当类的属性使用可变对象作为默认值时,也可能会导致奇怪的问题。例如:
class Robot:
def __init__(self, name, commands=[]):
self.name = name
self.commands = commands
robot1 = Robot('R2-D2')
robot2 = Robot('C-3PO')
robot1.commands.append('move forward')
robot2.commands.append('turn left')
print(robot1.commands) # 输出:['move forward', 'turn left']
print(robot2.commands) # 输出:['move forward', 'turn left']
在上面的代码中,我们定义了一个名为 Robot
的类,并为其 __init__
方法的两个参数 name
和 commands
设置了默认值 []
。然后,我们创建了两个 Robot
类的实例,并向它们的 commands
属性中添加了命令。最后,我们分别输出了两个实例的 commands
属性值。
可以看到,虽然我们只向 robot1
实例的 commands
属性中添加了 'move forward'
命令,但是 robot2
实例的 commands
属性中也包含了该命令。这是因为,类的属性默认值是被所有实例所共享的。
如果我们希望避免这个问题,可以在类的方法内部创建一个新的列表,并将其作为属性的默认值。例如:
class Robot_v2:
def __init__(self, name, commands=None):
self.name = name
self.commands = [] if commands is None else commands
robot1 = Robot_v2('R2-D2')
robot2 = Robot_v2('C-3PO')
robot1.commands.append('move forward')
robot2.commands.append('turn left')
print(robot1.commands) # 输出:['move forward']
print(robot2.commands) # 输出:['turn left']
在上面的代码中,我们重新定义了一个名为 Robot_v2
的类,并在其 __init__
方法中判断属性 commands
是否为 None
。如果 commands
为 None
,则创建一个新的空列表作为属性的默认值。然后,我们创建了两个 Robot_v2
类的实例,并向它们的 commands
属性中添加了命令。最后,我们分别输出了两个实例的 commands
属性值。
可以看到,虽然我们向 robot1
实例的 commands
属性中添加了 'move forward'
命令,但是 robot2
实例的 commands
属性中并不包含该命令。这是因为,我们在 Robot_v2
类的 __init__
方法中,为每个实例创建了一个新的空列表作为 commands
属性的默认值,从而避免了默认值被所有实例所共享的问题。
结论
在 Python 中,当我们没有为函数或变量提供任何值时,它们的默认值取决于我们在定义时所设置的默认值。对于函数中的参数,默认值可以是任意对象;对于变量和类的属性,默认值也可以是任意对象。需要注意的是,当使用可变对象作为参数或属性的默认值时,可能会出现共享默认值的问题,需要特别注意。为避免这个问题,可以在函数或方法内部创建一个新的可变对象,并将其作为默认值。