**
(Çift yıldız) ve *
(yıldız) parametreler için ne yapar
İşlevlerin kabul edilmesini ve kullanıcıların herhangi bir sayıda argüman, pozisyon ( *
) ve anahtar kelime ( **
) iletmesini sağlarlar .
Fonksiyonların Tanımlanması
*args
adlı bir tuple grubuna atanacak herhangi bir sayıda isteğe bağlı konumsal argümana (parametre) izin verir args
.
**kwargs
adında bir dikte olacak herhangi bir sayıda isteğe bağlı anahtar kelime argümanı (parametresi) sağlar kwargs
.
Herhangi bir uygun ismi seçebilirsiniz (ve seçmelisiniz), ancak amaç argümanların spesifik olmayan anlambilimsel olması args
ve kwargs
standart isimler olmasıdır.
Genişletme, İstenen sayıda argümanın iletilmesi
Ayrıca kullanabilir *args
ve **kwargs
sırasıyla listeleri (veya herhangi iterable) ve dicts (veya herhangi bir haritalama) den parametrelerinde geçmesine.
Parametreleri alan fonksiyonun genişletildiklerini bilmek zorunda değildir.
Örneğin, Python 2'nin xrange'i açıkça beklemez *args
, ancak bağımsız değişken olarak 3 tamsayıyı aldığından:
>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x) # expand here
xrange(0, 2, 2)
Başka bir örnek olarak, dict genişlemesini şu alanlarda kullanabiliriz str.format
:
>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'
Python 3'teki yenilikler: Yalnızca anahtar kelime bağımsız değişkenleriyle işlevleri tanımlama
Sen olabilir ancak argümanları anahtar kelime sonra *args
örneğin burada, - kwarg2
bir anahtar kelime argüman olarak verilmelidir - değil pozisyonel:
def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs):
return arg, kwarg, args, kwarg2, kwargs
Kullanımı:
>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})
Ayrıca, *
sınırsız konumsal argümanlara izin vermeden, yalnızca anahtar kelime argümanlarının takip ettiğini belirtmek için tek başına kullanılabilir.
def foo(arg, kwarg=None, *, kwarg2=None, **kwargs):
return arg, kwarg, kwarg2, kwargs
Burada, kwarg2
yine açıkça adlandırılmış bir anahtar kelime argümanı olmalıdır:
>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})
Ve artık sınırsız konumsal argümanı kabul edemeyiz çünkü elimizde *args*
:
>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments
but 5 positional arguments (and 1 keyword-only argument) were given
Yine, daha basit olarak, burada kwarg
konumsal olarak değil, isimle verilmemizi istiyoruz:
def bar(*, kwarg=None):
return kwarg
Bu örnekte, kwarg
konumsal olarak geçmeye çalışırsak bir hata alırız:
>>> bar('kwarg')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given
kwarg
Parametreyi bir anahtar kelime argümanı olarak açıkça geçmeliyiz.
>>> bar(kwarg='kwarg')
'kwarg'
Python 2 uyumlu demolar
*args
(tipik olarak "yıldız-args" olarak adlandırılır) ve **kwargs
(yıldızlar "kwargs" diyerek ima edilebilir, ancak "çift yıldız kwargs" ile açık olun), Python'un *
ve **
gösterimini kullanmak için yaygın olarak kullanılan deyimleridir . Bu belirli değişken adları gerekli değildir (örn kullanabilirdin *foos
ve**bars
), ancak konvansiyondan ayrılma muhtemelen Python kodlayıcılarınızı öfkelendirecektir.
Bunları genellikle işlevimizin ne alacağını veya kaç argümanı alacağımızı bilmediğimizde ve bazen her değişkeni ayrı olarak adlandırdığımızda bile çok dağınık ve gereksiz olur (ancak bu genellikle açık olan bir durumdur) örtükten daha iyi).
örnek 1
Aşağıdaki işlev, bunların nasıl kullanılabileceğini açıklar ve davranışı gösterir. Belirtilen b
argümanın, aşağıdaki ikinci konumsal argüman tarafından kullanılacağını unutmayın :
def foo(a, b=10, *args, **kwargs):
'''
this function takes required argument a, not required keyword argument b
and any number of unknown positional arguments and keyword arguments after
'''
print('a is a required argument, and its value is {0}'.format(a))
print('b not required, its default value is 10, actual value: {0}'.format(b))
# we can inspect the unknown arguments we were passed:
# - args:
print('args is of type {0} and length {1}'.format(type(args), len(args)))
for arg in args:
print('unknown arg: {0}'.format(arg))
# - kwargs:
print('kwargs is of type {0} and length {1}'.format(type(kwargs),
len(kwargs)))
for kw, arg in kwargs.items():
print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
# But we don't have to know anything about them
# to pass them to other functions.
print('Args or kwargs can be passed without knowing what they are.')
# max can take two or more positional args: max(a, b, c...)
print('e.g. max(a, b, *args) \n{0}'.format(
max(a, b, *args)))
kweg = 'dict({0})'.format( # named args same as unknown kwargs
', '.join('{k}={v}'.format(k=k, v=v)
for k, v in sorted(kwargs.items())))
print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
dict(**kwargs), kweg=kweg))
İle Biz işlevin imza için online yardım kontrol edebilirsiniz help(foo)
söyler, hangi
foo(a, b=10, *args, **kwargs)
Bu işlevi foo(1, 2, 3, 4, e=5, f=6, g=7)
hangi baskılar:
a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args)
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns:
{'e': 5, 'g': 7, 'f': 6}
ÖRNEK 2
Ayrıca, sadece sağladığımız başka bir işlev kullanarak da çağırabiliriz a
:
def bar(a):
b, c, d, e, f = 2, 3, 4, 5, 6
# dumping every local variable into foo as a keyword argument
# by expanding the locals dict:
foo(**locals())
bar(100)
baskılar:
a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args)
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns:
{'c': 3, 'e': 5, 'd': 4, 'f': 6}
Örnek 3: Dekoratörlerde pratik kullanım
Tamam, belki de programı henüz görmüyoruz. Bu nedenle, farklılaştırma kodundan önce ve / veya sonra yedek kod içeren çeşitli işlevleriniz olduğunu düşünün. Aşağıdaki adlandırılmış işlevler, açıklama amacıyla yalnızca sözde koddur.
def foo(a, b, c, d=0, e=100):
# imagine this is much more code than a simple function call
preprocess()
differentiating_process_foo(a,b,c,d,e)
# imagine this is much more code than a simple function call
postprocess()
def bar(a, b, c=None, d=0, e=100, f=None):
preprocess()
differentiating_process_bar(a,b,c,d,e,f)
postprocess()
def baz(a, b, c, d, e, f):
... and so on
Bunu farklı bir şekilde ele alabiliriz, ancak artıklığı bir dekoratörle kesinlikle çıkarabiliriz ve bu nedenle aşağıdaki örneğimiz nasıl *args
ve **kwargs
çok yararlı olabileceğini göstermektedir :
def decorator(function):
'''function to wrap other functions with a pre- and postprocess'''
@functools.wraps(function) # applies module, name, and docstring to wrapper
def wrapper(*args, **kwargs):
# again, imagine this is complicated, but we only write it once!
preprocess()
function(*args, **kwargs)
postprocess()
return wrapper
Ve artık, sarılı her işlev, fazlalığı hesaba kattığımız için çok daha özlü bir şekilde yazılabilir:
@decorator
def foo(a, b, c, d=0, e=100):
differentiating_process_foo(a,b,c,d,e)
@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
differentiating_process_bar(a,b,c,d,e,f)
@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
differentiating_process_baz(a,b,c,d,e,f, g)
@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
differentiating_process_quux(a,b,c,d,e,f,g,h)
Ve yapmamıza izin veren *args
ve **kwargs
kodumuzu hesaba katarak, kod satırlarını azaltıyor, okunabilirliği ve sürdürülebilirliği geliştiriyoruz ve programımızdaki mantık için tek kanonik konumlara sahibiz. Bu yapının herhangi bir bölümünü değiştirmemiz gerekiyorsa, her değişikliği yapabileceğimiz bir yerimiz var.