2013-06-17 12 views
5

Załóżmy Chciałem napisać funkcję podobną do rangeDefinicja funkcji jak zakresie

Przypomnijmy, że zakres ten formularz jeden argument i 2/3 argument:

class range(object) 
| range(stop) -> range object 
| range(start, stop[, step]) -> range object 

Gdybym chciał metodę lub funkcję mają ten sam interfejs, czy istnieje bardziej elegancki sposób niż to:

def range_like(*args): 
    start,stop,step=[None]*3 
    if len(args)==1: 
     stop=args[0] 
    elif len(args)==2: 
     start,stop=args 
    elif len(args)==3: 
     start,stop,step=args 
    else: 
     raise ValueError  
    print(start,stop,step) 

Odpowiedz

5

Niedużo sugerować tutaj, ale alternatywą może być za pomocą opcjonalnych argumentów i wymieniając dwie pierwsze jeśli tylko jeden otrzymali:

def range_like(start, stop=None, step=1): 
    if stop is None: 
     start, stop = 0, start 
    ... 
+3

Nie oddałem głosu, ale obie twoje odpowiedzi mają problem, jeśli "Brak" jest poprawnym argumentem. Rozważmy 'slice()', który przyjmuje podobne argumenty, 'slice (1)' musi być równoważne 'slice (None, 1, None)', ale 'slice (1, None)' musi odpowiadać 'slice (1 , Brak, Brak) '. –

+1

w takim przypadku możesz użyć obiektów wartownika. ale używanie Brak jako brakującego znacznika argumentu jest standardową praktyką Pythona. –

4

chciałbym napisać to jako:

def range_like(start=None, stop=None, step=1): 
    if stop is None: 
     start, stop = stop, start 
    ... 

jeśli to, co chcesz?

[aktualizacja] można również dodać:

if stop is start is None: 
     raise ValueError() 

również użyć Sentinel obiektów zamiast None (to nie jest normalne w Pythonie, ale widać go czasami):

NOTSET = object() 
def range_like(start=NOTSET, stop=NOTSET, step=1): 
    if stop is NOTSET: 
     start, stop = stop, start 

, która umożliwia None jako argument.

+1

dlaczego to dostać dwa downvotes? inne osoby od tego czasu opublikowały prawie identyczne odpowiedzi. co robimy źle? jeśli przegłosujesz, wyjaśnij dlaczego. –

+2

Należy wyjaśnić, że pierwszy argument nie jest opcjonalny. Jeśli użyjesz 'def range_like (start, stop = None, step = 1)' zamiast tego, wywołanie 'range_like()' spowoduje bardziej przydatny komunikat błędu. – FastTurtle

2

Nie można zrobić opcjonalny argument pojawia się przed obowiązkowymi argumentów.

Można opracować obejścia jak argumenty wymieniających:

def range_like(s, t=None, u=None): 
    if t is None: 
     s,t = t,s 
Powiązane problemy