Pek çok cevapta tam bilginin küçük parçaları var, bu yüzden hepsini en sevdiğim kalıplarla bir araya getirmek istiyorum.
varsayılan değer bir mutable
türdür
Varsayılan değer değiştirilebilir bir nesneyse, şanslısınız: Python'un varsayılan argümanlarının işlev tanımlandığında bir kez değerlendirildiği gerçeğinden yararlanabilirsiniz (bununla ilgili olarak son bölümdeki cevabın sonunda biraz daha fazlası var)
Bu is
, işlev veya yöntem olarak aşağıdaki örneklerde olduğu gibi, bir bağımsız değişken olarak iletilip aktarılmadığını görmek için varsayılan değişken bir değeri kullanarak kolayca karşılaştırabileceğiniz anlamına gelir :
def f(value={}):
if value is f.__defaults__[0]:
print('default')
else:
print('passed in the call')
ve
class A:
def f(self, value={}):
if value is self.f.__defaults__[0]:
print('default')
else:
print('passed in the call')
Değişmez varsayılan argümanlar
Şimdi, varsayılan immutable
değerinizin bir değer olması bekleniyorsa (ve dizelerin bile değişmez olduğunu unutmayın!) Çünkü hileyi olduğu gibi kullanamazsınız, ancak yine de yapabileceğiniz bir şey var, yine de değişken tip; temelde işlev imzasına değişebilir bir "sahte" varsayılan ve işlev gövdesine istenen "gerçek" varsayılan değeri koyarsınız .
def f(value={}):
"""
my function
:param value: value for my function; default is 1
"""
if value is f.__defaults__[0]:
print('default')
value = 1
else:
print('passed in the call')
print(value)
Eğer gerçek varsayılan değeriniz ise özellikle komiktir None
, ancak None
değişmezdir, bu yüzden ... yine de fonksiyon varsayılan parametresi olarak bir değişkene açık bir şekilde kullanmanız ve kodda Yok'a geçmeniz gerekir.
Default
Değişmez varsayılanlar için bir sınıf kullanma
veya @cz önerisine benzer şekilde, python belgeleri yeterli değilse :-), API'yi daha açık hale getirmek için araya bir nesne ekleyebilirsiniz (belgeleri okumadan); used_proxy_ Default sınıf örneği değiştirilebilir ve kullanmak istediğiniz gerçek varsayılan değeri içerecektir.
class Default:
def __repr__(self):
return "Default Value: {} ({})".format(self.value, type(self.value))
def __init__(self, value):
self.value = value
def f(default=Default(1)):
if default is f.__defaults__[0]:
print('default')
print(default)
default = default.value
else:
print('passed in the call')
print("argument is: {}".format(default))
şimdi:
>>> f()
default
Default Value: 1 (<class 'int'>)
argument is: 1
>>> f(2)
passed in the call
argument is: 2
Yukarıdakiler için de güzel çalışıyor Default(None)
.
Diğer desenler
Açıkça görülüyor ki, yukarıdaki modeller olması gerekenden daha çirkin görünüyor çünkü print
bunların hepsi nasıl çalıştıklarını göstermek için var. Aksi takdirde onları yeterince kısa ve tekrarlanabilir buluyorum.
Eklenecek bir dekoratör yazabilirim __call__
dışarı bölmek gerekir - daha aerodinamik şekilde @dmg önerdiği model, ama bu hala işlev tanımı kendi içinde garip hileler kullanmak mecbur edecek value
ve value_default
böylece, kod gerek ayırt etmek ise onları Pek avantaj görmüyorum ve örneği yazmayacağım :-)
Python'da varsayılan değerler olarak değişken türler
# 1 python gotcha hakkında biraz daha fazla bilgi ! , yukarıda kendi zevkiniz için istismar edilmiş. Tanımdaki değerlendirmeden dolayı neler olduğunu aşağıdaki şekilde görebilirsiniz :
def testme(default=[]):
print(id(default))
İstediğiniz kadar çalıştırabilirsiniz testme()
, her zaman aynı varsayılan örneğe bir referans göreceksiniz (yani temelde varsayılanınız değişmez :-)).
Python olduğunu unutmayın sadece 3 değişken yerleşik türleri : set
, list
, dict
; diğer her şey - dizeler bile! - değişmezdir.