在简单的 dict 上使用 kwargs(或 args)有什么好处?
What is the benefit of using kwargs (or args) over a simple dict?
我想知道为什么我应该使用 kwargs 或 args 而不是传递一个简单的字典(或 args 的元组)?
我写了一个非常简单的代码片段来检查到底发生了什么,但我找不到任何专业人士在 dict 上使用 kwargs。如果有人能告诉我为什么要使用那些我会很高兴。
现在我可以看到它更像 pythonic 但没有任何区别。此外,如果您使用简单的字典,那么它会更具可读性,因为所有语言都可以做到这一点,但不是 kwargs 方式。
def test_normal(input: dict):
for element in input.items():
print('Type: {}, raw: {}'.format(type(input), input))
print('key: {}, value: {}'.format(element[0], element[1]))
def test_kwargs(**kwargs):
for element in kwargs.items():
print('Type: {}, raw: {}'.format(type(kwargs), kwargs))
print('key: {}, value: {}'.format(element[0], element[1]))
test_normal(dict(name='Joseph'))
test_kwargs(name='Joseph')
Type: <class 'dict'>, raw: {'name': 'Joseph'}
key: name, value: Joseph
Type: <class 'dict'>, raw: {'name': 'Joseph'}
key: name, value: Joseph
这些是不同的东西,都有它们的用例。只是一个经验法则:如果它看起来像一个函数参数,它应该是一个函数参数。
*args
和 **kwargs
有几个简洁的用例。其中之一是传递此时您不关心的参数:
假设您有 class Base
和 class A
继承自 Base
:
class Base:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
class A(Base):
def __init__(self, n, *args, **kwargs):
super().__init__(*args, **kwargs)
self.n = n
如你所见,class A
不关心 Base
的 __init__
参数,所以它只是传递所有内容(除了 n
它需要)向前。因此,如果您要更改 Base
的 __init__
,则不需要更改 A
.
但是当您创建 A
对象时,您将正常传递参数:
a = A(5, 3, y=6, z=42)
类似的想法是当你实现一个装饰器时,你想在一个函数上使用任何种类和数量的参数:
def say_hello_first(fn):
def wrapper(*args, *kwargs):
print('Hello')
return fn(*args, **kwargs)
return wrapper
@say_hello_first
def foo(x):
print(x)
@say_hello_first
def bar(a, b, c=3.14):
print((a + b) * c)
然后:
>>> foo(42)
Hello
42
>>> bar(1, 2, c=3)
Hello
9
我想知道为什么我应该使用 kwargs 或 args 而不是传递一个简单的字典(或 args 的元组)?
我写了一个非常简单的代码片段来检查到底发生了什么,但我找不到任何专业人士在 dict 上使用 kwargs。如果有人能告诉我为什么要使用那些我会很高兴。 现在我可以看到它更像 pythonic 但没有任何区别。此外,如果您使用简单的字典,那么它会更具可读性,因为所有语言都可以做到这一点,但不是 kwargs 方式。
def test_normal(input: dict):
for element in input.items():
print('Type: {}, raw: {}'.format(type(input), input))
print('key: {}, value: {}'.format(element[0], element[1]))
def test_kwargs(**kwargs):
for element in kwargs.items():
print('Type: {}, raw: {}'.format(type(kwargs), kwargs))
print('key: {}, value: {}'.format(element[0], element[1]))
test_normal(dict(name='Joseph'))
test_kwargs(name='Joseph')
Type: <class 'dict'>, raw: {'name': 'Joseph'}
key: name, value: Joseph
Type: <class 'dict'>, raw: {'name': 'Joseph'}
key: name, value: Joseph
这些是不同的东西,都有它们的用例。只是一个经验法则:如果它看起来像一个函数参数,它应该是一个函数参数。
*args
和 **kwargs
有几个简洁的用例。其中之一是传递此时您不关心的参数:
假设您有 class Base
和 class A
继承自 Base
:
class Base:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
class A(Base):
def __init__(self, n, *args, **kwargs):
super().__init__(*args, **kwargs)
self.n = n
如你所见,class A
不关心 Base
的 __init__
参数,所以它只是传递所有内容(除了 n
它需要)向前。因此,如果您要更改 Base
的 __init__
,则不需要更改 A
.
但是当您创建 A
对象时,您将正常传递参数:
a = A(5, 3, y=6, z=42)
类似的想法是当你实现一个装饰器时,你想在一个函数上使用任何种类和数量的参数:
def say_hello_first(fn):
def wrapper(*args, *kwargs):
print('Hello')
return fn(*args, **kwargs)
return wrapper
@say_hello_first
def foo(x):
print(x)
@say_hello_first
def bar(a, b, c=3.14):
print((a + b) * c)
然后:
>>> foo(42)
Hello
42
>>> bar(1, 2, c=3)
Hello
9