2010-03-22 11 views
68

Mam klasę z funkcją __init__.Jak zwrócić wartość z __init__ w Pythonie?

Jak mogę zwrócić liczbę całkowitą z tej funkcji, gdy obiekt jest tworzony?

Napisałem program, w którym __init__ wykonuje parsowanie linii komend i potrzebuję ustawić pewną wartość. Czy jest OK, ustawić ją w zmiennej globalnej i używać jej w innych funkcjach składowych? Jeśli tak, to jak to zrobić? Do tej pory zadeklarowałem zmienną poza klasą. a ustawienie jednej funkcji nie odzwierciedla innej funkcji?

+6

Jeśli rozważałeś zwrócenie kodu błędu, zamiast tego podnieś wyjątek. –

+0

Usuń komentarz i zaktualizuj swoje pytanie. Jesteś właścicielem pytania. To twoje pytanie. Napraw to pytanie, aby poprawnie pokazać, jaki jest twój prawdziwy problem. Nadużywasz '__init__'; możemy Ci pomóc, jeśli opisasz, co naprawdę chcesz osiągnąć. –

Odpowiedz

67

__init__ jest wymagane, aby powrócić Brak. Nie możesz (a przynajmniej nie powinieneś) zwrócić czegoś innego.

Spróbuj zrobić, co chcesz, aby zwrócić zmienną instancji (lub funkcję).

>>> class Foo: 
...  def __init__(self): 
...   return 42 
... 
>>> foo = Foo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: __init__() should return None 
+15

+1: Nie możesz ** zwrócić czegoś innego. To nie ma sensu. –

+63

__init__ nie zwraca nowo utworzonego obiektu - jak widać w TypeError, należy zwrócić Brak, prawda? Nowo utworzony obiekt jest zwracany przez __new__, __init__ po prostu ustawia niektóre z jego atrybutów. Ale tak, jak powiedziałeś, zmiana __init__ lub __new__, zwrócenie czegoś innego naprawdę nie ma sensu. – weronika

+0

Gdzie jest "nowy" tutaj? Czy w Pythonie jest "nowe"? Zakładam, że semantyka Pythona różni się od języka Java i innych języków, które używają tego słowa. –

8

__init__ nie zwraca niczego i zawsze powinny powrócić None.

37

Z documentation of __init__:

As a special constraint on constructors, no value may be returned; doing so will cause a TypeError to be raised at runtime.

Jako dowód, ten kod:

class Foo(object): 
    def __init__(self): 
     return 2 

f = Foo() 

daje ten błąd:

Traceback (most recent call last): 
    File "test_init.py", line 5, in <module> 
    f = Foo() 
TypeError: __init__() should return None, not 'int' 
85

Dlaczego chcesz to zrobić?

Jeśli chcesz powrócić jakiś inny przedmiot, gdy klasa jest nazywany, a następnie użyć metody __new__():

class MyClass(object): 
    def __init__(self): 
     print "never called in this case" 
    def __new__(cls): 
     return 42 

obj = MyClass() 
print obj 
+8

Tak, __new__ to właściwy sposób zwracania czegoś innego niż instancja klasy podczas korzystania z klasy ... Zastanawiam się - czy istnieje jakikolwiek powód, dla którego faktycznie mógłbyś chcieć to zrobić? – weronika

+22

@weronika Jedna idea: w każdej sytuacji, w której normalnie używasz fabryki, ale masz powody, by chcieć przedstawić interfejs, który wygląda jak normalna instancja klasy. Przykład: dodając kilka nowych opcjonalnych parametrów do '__init__' klasy, zdajesz sobie sprawę, że tak naprawdę, aby zapewnić wymaganą elastyczność, potrzebujesz fabryki klas, która zwraca instancje wyspecjalizowanych podklas. Ale użytkownicy Twojej biblioteki używają już istniejącego API. Aby ją zachować, zastępujesz '__new__', aby zwracać wystąpienia swoich wyspecjalizowanych podklas. –

+6

Jeśli chcesz zobaczyć przykład tego, co powiedział Mark Amery, sprawdź kod źródłowy modułu 'datetime' w Bibliotece standardowej. Używa '__new__' w dokładnie taki sposób. – Zearin

12

Sposób __init__, podobnie jak inne metody i funkcje zwróci None domyślnie w przypadku braku zwrotu oświadczenie, więc można napisać, że jak jeden z nich:

class Foo: 
    def __init__(self): 
     self.value=42 

class Bar: 
    def __init__(self): 
     self.value=42 
     return None 

Ale, oczywiście, dodając return None nie kupić nic.

Nie jestem pewien, co jesteś po, ale może być zainteresowany w jednym z nich:

class Foo: 
    def __init__(self): 
     self.value=42 
    def __str__(self): 
     return str(self.value) 

f=Foo() 
print f.value 
print f 

nadrukami:

42 
42 
+0

ohh..Can mogę uzyskać dostęp do zmiennej członka z klasy? To powinno rozwiązać mój problem .... dzięki –

+0

@lakshmipathi, tak, zmienne instancji takie jak ta są publiczne. – quamrana

+0

Jako oneliner, aby uzyskać coś wartościowego zwróconego po inicjacji klasy: 'f = Foo(). Wartość' – JLT

13

Próbka wykorzystanie danej sprawy może być jak :

class SampleObject(object) 

    def __new__(cls,Item) 
     if self.IsValid(Item): 
      return super(SampleObject, cls).__new__(cls) 
     else: 
      return None 

    def __init__(self,Item) 
     self.InitData(Item) #large amount of data and very complex calculations 

... 

ValidObjects=[] 
for i in data: 
    Item=SampleObject(i) 
    if Item:    # in case the i data is valid for the sample object 
     ValidObjects.Append(Item) 

nie mam wystarczająco dużo reputacji, więc nie mogę napisać komentarz, to ja szaleństwo!Chciałbym opublikować go jako komentarz do weronika

+1

Spowoduje to wywołanie NameError: 'self' nie jest zdefiniowany w' __new __ (cls, Item) ' –

2

Chciałem tylko dodać, można powrócić zajęcia w __init__

@property 
def failureException(self): 
    class MyCustomException(AssertionError): 
     def __init__(self_, *args, **kwargs): 
      *** Your code here *** 
      return super().__init__(*args, **kwargs) 

    MyCustomException.__name__ = AssertionError.__name__ 
    return MyCustomException 

Powyższa metoda pomaga wdrożyć konkretne działania momencie wyjątek w teście

+0

proszę rozwinąć ten kod. – nish

Powiązane problemy