2011-11-15 14 views
22

Chcę przekazać domyślny argument metody instancji, stosując wartość atrybutu instancji:Jak przekazać domyślną wartość argumentu członka instancji do metody?

class C: 
    def __init__(self, format): 
     self.format = format 

    def process(self, formatting=self.format): 
     print(formatting) 

Podczas próby, że pojawia się następujący komunikat o błędzie:

NameError: name 'self' is not defined 

chcę sposób zachowania się w następujący sposób:

C("abc").process()  # prints "abc" 
C("abc").process("xyz") # prints "xyz" 

Na czym polega problem, dlaczego to nie działa? I jak mogę to zrobić?

+0

nie używaj formatu jako nazwy zmiennej, ponieważ jest to wbudowana funkcja w pythonie. – Yajushi

+0

Edytowanie błędu "self" w "metodzie procesu" –

Odpowiedz

31

Nie można tak naprawdę zdefiniować tej wartości jako wartości domyślnej, ponieważ wartość domyślna jest oceniana, gdy metoda jest zdefiniowana przed wystąpieniem jakichkolwiek wystąpień. Łatwe obejście jest zrobić coś takiego:

class C: 
    def __init__(self, format): 
     self.format = format 

    def process(self, formatting=None): 
     formatting = formatting if formatting is not None else self.format 
     print(formatting) 

self.format będzie wykorzystywany jedynie, jeśli formatting jest None.


Aby zademonstrować punkt jak działają wartości domyślne, patrz poniższy przykład:

def mk_default(): 
    print("mk_default has been called!") 

def myfun(foo=mk_default()): 
    print("myfun has been called.") 

print("about to test functions") 
myfun("testing") 
myfun("testing again") 

a wyjście tutaj:

mk_default has been called! 
about to test functions 
myfun has been called. 
myfun has been called. 

Wskazówki jak mk_default została wywołana tylko raz, a że stało się zanim funkcja została kiedykolwiek wywołana!

+0

Wierzę, że 'mk_default' został wywołany przed wywołaniem funkcji, ponieważ' foo = mk_default() 'wywołało to z powodu nawiasu. Czy nie powinno to być 'foo = mk_default'? Twój przykład może się zmienić na 'myfun (" testing ")', po którym następuje 'myfun()'. – gary

+0

Czy to nadal zalecane rozwiązanie? – confused00

+2

Zauważ, że 'formatting = formatting lub self.format'odstawi' formatting' na 'self.format' jeśli' formatting' będzie wartością falsey, na przykład 0. To mnie ugryźć. Bezpieczniejszym sposobem jest wpisanie "formatting = formatowanie, jeśli formatowanie nie jest żadnym innym self.format" lub odpowiednikiem. – Godsmith

6

W języku Python nazwa self to , a nie. Jest to tylko konwencja dla nazwy parametru, dlatego istnieje self parametr w __init__. (Faktycznie, __init__ nie jest wyjątkowy albo, w szczególności robi nie faktycznie utworzyć obiekt ... to już historia)

C("abc").process() tworzy instancję C, patrzy metodę process w klasie C, i wywołuje tę metodę z instancją C jako pierwszym parametrem. Tak więc kończy się parametrem self, jeśli go podałeś.

Nawet jeśli miałeś ten parametr, nie możesz pisać czegoś takiego jak def process(self, formatting = self.formatting), ponieważ self nie ma jeszcze zasięgu w punkcie, w którym ustawiłeś wartość domyślną. W języku Python wartość domyślna parametru jest obliczana podczas kompilacji funkcji i "utknięcia" w funkcji. (Z tego samego powodu, jeśli używasz wartości domyślnej, takiej jak [], lista zapamiętuje zmiany między połączeniami do tej funkcji.)

Jak mogę to wykonać?

Tradycyjnym sposobem jest domyślne użycie None i sprawdzenie tej wartości i zastąpienie jej wewnątrz funkcji.Może się okazać, że trochę bezpieczniej jest zrobić specjalną wartość do tego celu (instancja object jest wszystkim, czego potrzebujesz, o ile ukryjesz ją, aby kod wywołujący nie używał tej samej instancji) zamiast None. Tak czy inaczej, powinieneś sprawdzić tę wartość za pomocą is, a nie ==.

+0

Twoje obejście nie odpowiada żądanemu wynikowi przy użyciu Brak. –

+0

Jeśli 'None' jest poprawną wartością' formatting', będziesz musiał wybrać coś innego, jak to wyjaśniłem. –

1

"self" należy przekazać jako pierwszy argument do dowolnej funkcji klasy, jeśli chcesz, aby zachowywały się one jako metody niestatyczne.

odnosi się do samego obiektu. Nie można przekazać "self" jako domyślnego argumentu, ponieważ jego pozycja jest poprawiona jako pierwszy argument.

W twoim przypadku zamiast "formatowanie = self.format" użytkowania "formatowania = None", a następnie przypisać wartość z kodem jak poniżej:

[EDIT]

class c: 
     def __init__(self, cformat): 
      self.cformat = cformat 

     def process(self, formatting=None): 
      print "Formating---",formatting 
      if formatting == None: 
       formatting = self.cformat 
       print formatting 
       return formatting 
      else: 
       print formatting 
       return formatting 

c("abc").process()   # prints "abc" 
c("abc").process("xyz")  # prints "xyz" 

Uwaga: Nie używaj "format" jako nazwa zmiennej, ponieważ jest wbudowaną funkcją w pytonie

+0

Cóż, poprawiłem problem z "self". Ale twoja odpowiedź nie spełnia pożądanego rezultatu. –

+0

sprawdź edytowany blok, to by ci pomogło. – Yajushi

Powiązane problemy