2009-03-09 9 views
4

bir böyle bir değere sahip Say birden çok değer:Python'da hem tek hem de çoklu değerleri kapsayacak tek uygulama</p> <p>n = 5</p> <p>ve bunun faktöriyelini döndüren şöyle bir yöntem:</p> <p>Faktoriyel (5)</p> <p>Nasıl yapmalıyım

nums = [1,2,3,4,5]

Faktöriyel (nums)

böylece tüm bu değerlerin özelliklerini bir liste olarak döndürür.

Bunu işlemenin en temiz yolu, 2 yöntem yazmadan nelerdir? Python'un bu tür durumlarla başa çıkmak için iyi bir yolu var mı?

+0

Skalerlerle ve başka vektörlerle bir şey yapan böyle büyülü bir işlev için kullanım durumu hakkında biraz bilgi verebilir misiniz? –

+0

Elbette. Tek bir değer çok kullanışlı görünmese de, Sum veya Ortalama veya benzeri işlevler için iyidir. Böyle kullanılabilecek birçok fonksiyon var. –

+0

Hayır, sadece tek bir değeriniz varsa, bu tek değeri içeren bir liste kullanın. Nesneler benzer davrandığında farklı türler döndürülür. Ama buradaki sınırın çok üzerinde. –

cevap

7

Bu bazen yapılır: Eğer Factorial gövdesi TypeError yükseltmek asla eminseniz için

, bu basitleştirilmiş olabilir.

def factorial(*args): 
    def fact(n): 
     if n == 0: return 1 
     return n*fact(n-1) 
    return [ fact(a) for a in args ] 

Basit değerler ve sekanslarla çalışan neredeyse sihirli bir işlev verir.

>>> factorial(5) 
[120] 
>>> factorial(5, 6, 7) 
[120, 720, 5040] 
>>> factorial(*[5, 6, 7]) 
[120, 720, 5040] 
+0

Şimdiye kadarki en temiz cevap ... –

+0

Girdi basit bir sayı olsa bile bir liste döndürdüğü için iyi değil. –

+0

Gereksinimlerin ne olduğu konusunda tamamen açık değilim. Liste ve bireysel değerleri "tekdüze" biçimde sihirli bir şekilde işleyen bir işlev fikri kafa karıştırıcıdır. Ya da APL (veya J veya K). –

9

List comprehension:

[fac(n) for n in nums] 

DÜZENLEME:

Üzgünüm, her iki dizileri ve tek değerleri işleyen bir yöntem istiyor yanlış? Bunu neden iki yöntemle yapmayacağını hayal bile edemiyorum.

def factorial(n): 
    # implement factorial here 
    return answer 

def factorial_list(nums): 
    return [factorial(n) for n in nums] 

alternatif bunu yapmak için bazı korkunç önemli neden yoksa daha iyi kaçınılmalıdır tip denetimi, çeşit yapmak olacaktır.

DÜZENLEME 2:

MizardX cevabı daha iyidir, o biri için oy. Şerefe.

+0

Aslında cevabınızı daha çok beğeniyorum. Bunu bir işlev olarak yazarak daha fazla haberci kodu yazmayı düşünüyorum. – daf

+0

Eh, ben de öyle: P Ama MizardX, benim yapmadığım sorusunu cevaplandırdı, bu yüzden tek adil oyu aldı. :) – bouvard

+0

Teşekkürler Bir koleksiyon kullandığınızda python doğru işlevi nasıl buluyor? –

6

Python'un aşırı yükleme yöntemi yapıp yapamayacağını sorarsanız: hayır. Bu nedenle, bu gibi çok-yöntemlerin yapılması, bir yöntemi tanımlamak için oldukça Pythonic olmayan bir yoldur. Ayrıca, adlandırma kuralı genellikle büyük harf sınıf adları ve küçük harf işlevleri/yöntemleri. Eğer fantezi hissediyorsanız, herhangi işleve yapar bir dekoratör yapabilir,

def Factorial(arg): 
    if getattr(arg, '__iter__', False): # checks if arg is iterable 
    return [Factorial(x) for x in arg] 
    else: 
    # ... 

Veya: zaten önde gitmek isterseniz

, basit yolu sadece bir dal oluşturmak için olacaktır:

def autoMap(f): 
    def mapped(arg): 
     if getattr(arg, '__iter__', False): 
      return [mapped(x) for x in arg] 
     else: 
      return f(arg) 
    return mapped 

@autoMap 
def fact(x): 
    if x == 1 or x == 0: 
     return 1 
    else: 
     return fact(x-1) + fact(x-2) 

>>> fact(3) 
3 
>>> fact(4) 
5 
>>> fact(5) 
8 
>>> fact(6) 
13 
>>> fact([3,4,5,6]) 
[3, 5, 8, 13] 

daha Pythonic bir şekilde değişken bağımsız değişken uzunluklarının kullanmak da:

def autoMap2(f): 
    def mapped(*arg): 
     if len(arg) != 1: 
      return [f(x) for x in arg] 
     else: 
      return f(arg[0]) 
    return mapped 

@autoMap2 
def fact(n): 
# ... 

>>> fact(3,4,5,6) 
[3, 5, 8, 13] 

P Derin bir haritalama dekoratör bir araya ikisini Utting: Bu iterable ise

def autoDeepMap(f): 
    def mapped(*args): 
     if len(args) != 1: 
      return [mapped(x) for x in args] 
     elif getattr(args[0], '__iter__', False): 
      return [mapped(x) for x in args[0]] 
     else: 
      return f(args[0]) 
    return mapped 

@autoDeepMap 
def fact(n): 
# ... 

>>> fact(0) 
1 
>>> fact(0,1,2,3,4,5,6) 
[1, 1, 2, 3, 5, 8, 13] 
>>> fact([0,1,2,3,4,5,6]) 
[1, 1, 2, 3, 5, 8, 13] 
>>> fact([0,1,2],[3,4,5,6]) 
[[1, 1, 2], [3, 5, 8, 13]] 
>>> fact([0,1,2],[3,(4,5),6]) 
[[1, 1, 2], [3, [5, 8], 13]] 
+0

[arg (x) için x için f (x) 'yi arg içinde x için [mapped (x)] olarak değiştirerek dekoratörün yinelemesini yapabilirsiniz. –

+0

MizardX: Sadece aklımı uçurdun. Güzel fikir :) –

+0

Ama bu fibonacci ... :) –

13
def Factorial(arg): 
    try: 
     it = iter(arg) 
    except TypeError: 
     pass 
    else: 
     return [Factorial(x) for x in it] 
    return math.factorial(arg) 

, recursivly geçerlidir. Aksi takdirde normal şekilde ilerleyin.

Alternatif olarak, son return'u except bloğuna taşıyabilirsiniz.

def Factorial(arg): 
    try: 
     return [Factorial(x) for x in arg] 
    except TypeError: 
     return math.factorial(arg) 
+0

getattr (obj, '__iter__', False), 'obj' denemeden/denemeden (daha yavaş olabilir) yinelenebilir olup olmadığını kontrol etmenin bir yoludur. –

+0

@Andrey Fedorov: Çoğu durumda, try/except aslında daha hızlıdır. –

+0

@MizardX: "Factorial" ın bedeni önünüzde. Bu nedenle, 'arg' tekrar edilebilir olmadığında' TypeError' * 'ın * yükseltileceğinden emin olabilirsiniz. Faktörün yukarıdaki iki versiyonu da aynı şeyi yapıyor, ancak bir tanesi daha basit. – jfs

3

Yoksa liste anlama sözdizimi gibi ve yeni bir yöntem olan atlamak istemiyorsanız:

def factorial(num): 
    if num == 0: 
     return 1 
    elif num > 0: 
     return num * factorial(num - 1) 
    else: 
     raise Exception("Negative num has no factorial.") 

nums = [1, 2, 3, 4, 5] 
# [1, 2, 3, 4, 5] 

map(factorial, nums) 
# [1, 2, 6, 24, 120, 720] 
3

Sen NumPy/scipy en vectorize bir göz atmak isteyebilirsiniz. numpy dünyada

, dün durum ham yerine tek öğeli numpy dizi döndüren not rağmen

vFactorial=np.vectorize(Factorial) 
    vFactorial([1,2,3,4,5]) 
    vFactorial(6) 

gibi şeyler yapardım senin tek int-arg Faktoriyel fonksiyonu, verilen int.

İlgili konular