Bagaimana cara mengembalikan nilai dari __init__ dengan Python?

103

Saya memiliki kelas dengan suatu __init__fungsi.

Bagaimana cara mengembalikan nilai integer dari fungsi ini ketika sebuah objek dibuat?

Saya menulis sebuah program, di mana __init__parsing baris perintah dan saya perlu menetapkan beberapa nilai. Apakah OK mengaturnya di variabel global dan menggunakannya di fungsi anggota lainnya? Jika demikian, bagaimana cara melakukannya? Sejauh ini, saya mendeklarasikan variabel di luar kelas. dan mengaturnya satu fungsi tidak mencerminkan fungsi lain ??

webminal.org
sumber
8
Jika Anda mempertimbangkan untuk mengembalikan kode kesalahan, buat pengecualian sebagai gantinya.
JoeG
1
Harap hapus komentar Anda dan perbarui pertanyaan Anda. Anda pemilik pertanyaannya. Itu pertanyaanmu. Harap perbaiki pertanyaan untuk menunjukkan dengan benar apa masalah Anda yang sebenarnya. Anda menyalahgunakan __init__; kami dapat membantu Anda jika Anda menjelaskan apa yang sebenarnya ingin Anda capai.
S. Lott

Jawaban:

119

__init__diperlukan untuk mengembalikan Tidak ada. Anda tidak dapat (atau setidaknya tidak) mengembalikan sesuatu yang lain.

Coba buat apa pun yang Anda inginkan untuk mengembalikan variabel instan (atau fungsi).

>>> 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
Can Berk Güder
sumber
24
+1: Anda tidak dapat mengembalikan yang lain. Ini tidak masuk akal.
S. Lotot
72
init tidak mengembalikan objek yang baru dibuat - seperti yang terlihat di TypeError, itu diperlukan untuk mengembalikan None, bukan? Objek yang baru dibuat dikembalikan oleh new , init hanya menyetel beberapa atributnya. Tapi ya, seperti yang Anda katakan, mengubah init , atau baru , mengembalikan sesuatu yang lain benar-benar tidak masuk akal.
weronika
Dimana newdisini? Apakah newtersirat dalam Python? Saya berasumsi semantik Python berbeda dari Java dan bahasa lain yang menggunakan kata ini.
cs95
1
@Shiva AFAIK, dengan weronika baru berarti __new __ (sendiri) bukan semantik java umum.
Harsh Daftary
2
Hanya karena itu tidak bisa dilakukan bukan berarti itu tidak masuk akal. Misalnya, akan menyenangkan untuk meneruskan data dari super().__init__ke kelas turunan tanpa harus menyampaikannya melalui variabel instan.
cz
123

Mengapa Anda ingin melakukan itu?

Jika Anda ingin mengembalikan beberapa objek lain saat kelas dipanggil, gunakan __new__()metode:

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

obj = MyClass()
print obj
Jacek Konieczny
sumber
9
Ya, baru adalah cara yang benar untuk mengembalikan sesuatu selain contoh kelas saat menggunakan kelas ... Saya hanya ingin tahu - adakah alasan Anda benar-benar ingin MELAKUKAN itu?
weronika
33
@weronika Satu gagasan: dalam situasi apa pun di mana Anda biasanya menggunakan pabrik, tetapi Anda punya alasan untuk ingin menyajikan antarmuka yang terlihat seperti instansiasi kelas normal. Contoh: saat menambahkan beberapa parameter opsional baru ke dalam kelas __init__Anda, Anda menyadari bahwa sebenarnya, untuk memberikan fleksibilitas yang Anda inginkan, Anda memerlukan pabrik kelas yang mengembalikan instance subkelas khusus. Tapi pengguna perpustakaan Anda sudah menggunakan API yang ada. Untuk mempertahankannya, Anda mengganti __new__untuk mengembalikan instance subkelas khusus Anda.
Mark Amery
10
Jika Anda ingin melihat contoh dari apa yang dikatakan Mark Amery, lihat kode sumber datetimemodul dari Perpustakaan Standar. Ini digunakan __new__dengan cara yang persis seperti ini.
Zearin
Juga jika ada yang ingin melakukan ini pastikan untuk mewarisi dari objek jika tidak maka tidak akan berhasil.
Mino_e
Saya agak berpikir pada pount ini, hanya menggunakan fungsi biasa lebih masuk akal. Mungkin agak asing bagi orang-orang dari dimensi Java (fungsinya bukan di kelas? Bid'ah!) Tapi pythonic nya. (Anda juga dapat menetapkan properti ke fungsi seperti di funtionName.val = .. yang agak liar tetapi berhasil)
Shayne
37

Dari dokumentasi__init__ :

Sebagai batasan khusus pada konstruktor, tidak ada nilai yang dapat dikembalikan; melakukan hal itu akan menyebabkan TypeError dimunculkan saat runtime.

Buktinya, kode ini:

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

f = Foo()

Memberikan kesalahan ini:

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

Contoh Penggunaan materi yang dimaksud bisa seperti:

class SampleObject(object):

    def __new__(cls, item):
        if cls.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)

Saya tidak punya cukup reputasi jadi saya tidak bisa menulis komentar, ini gila! Saya berharap saya bisa mempostingnya sebagai komentar ke weronika

PMN
sumber
3
Ini akan memunculkan NameError: selftidak ditentukan di__new__(cls, Item)
Hart Simha
15

The __init__metode, seperti metode dan fungsi pengembalian lainnya ada secara default dengan tidak adanya pernyataan kembali, sehingga Anda dapat menulis seperti salah satu dari ini:

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

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

Namun, tentu saja, menambahkan return Nonetidak akan memberi Anda manfaat apa pun.

Saya tidak yakin apa yang Anda cari, tetapi Anda mungkin tertarik dengan salah satu dari ini:

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

f=Foo()
print f.value
print f

cetakan:

42
42
quamrana
sumber
ohh..Dapatkah saya mengakses variabel anggota di luar kelas? Maka itu seharusnya menyelesaikan masalah saya .... terima kasih
webminal.org
@lakshmipathi, Ya, variabel instan seperti ini adalah publik.
quamrana
Sebagai satu perjalanan untuk mendapatkan sesuatu yang berharga dikembalikan setelah inisiasi kelas:f = Foo().value
JLT
@ JLT Ya, Anda cam selalu melakukan itu tetapi itu tetap tidak berarti bahwa apa pun dikembalikan __init__.
quamrana
7

__init__tidak mengembalikan apapun dan harus selalu kembali None.

gruszczy.dll
sumber
4

Anda bisa mengaturnya ke variabel kelas dan membacanya dari program utama:

class Foo:
    def __init__(self):
        #Do your stuff here
        self.returncode = 42
bar = Foo()
baz = bar.returncode
PythonPro
sumber
2

Hanya ingin menambahkan, Anda dapat mengembalikan kelas __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

Metode di atas membantu Anda menerapkan tindakan tertentu pada Pengecualian dalam pengujian Anda


sumber
2
super().__init__kembali None, jadi Anda kembali None, yang tidak masalah, tapi mubazir.
cz
2

init () mengembalikan nilai tidak ada yang diselesaikan dengan sempurna

class Solve:
def __init__(self,w,d):
    self.value=w
    self.unit=d
def __str__(self):
    return str("my speed is "+str(self.value)+" "+str(self.unit))
ob=Solve(21,'kmh')
print (ob)

keluaran: kecepatan saya adalah 21 kmh

vikram singh gurjar
sumber
-2

Nah, jika Anda tidak peduli dengan instance objek lagi ... Anda bisa menggantinya!

class MuaHaHa():
def __init__(self, ret):
    self=ret

print MuaHaHa('foo')=='foo'
cosmo
sumber
2
Itu hanya mengubah apa yang ditugaskan ke nama selfdi dalam konstruktor itu.
Ondrej K.