2010-03-22 48 views
68

Tôi có một lớp học với chức năng __init__.Cách trả về giá trị từ __init__ bằng Python?

Làm cách nào để trả về giá trị số nguyên từ hàm này khi đối tượng được tạo?

Tôi đã viết một chương trình, trong đó __init__ thực hiện phân tích cú pháp dòng lệnh và tôi cần phải có một số giá trị được đặt. Có OK đặt nó trong biến toàn cục và sử dụng nó trong các hàm thành viên khác không? Nếu vậy làm thế nào để làm điều đó? Cho đến nay, tôi đã tuyên bố một biến bên ngoài lớp học. và thiết lập nó một chức năng không phản ánh trong chức năng khác?

+6

Nếu bạn đang cân nhắc việc trả lại mã lỗi, hãy tăng ngoại lệ thay thế. –

+0

Vui lòng xóa nhận xét của bạn và cập nhật câu hỏi của bạn. Bạn sở hữu câu hỏi. Đó là câu hỏi của bạn. Vui lòng sửa câu hỏi để hiển thị chính xác vấn đề thực sự của bạn là gì. Bạn đang lạm dụng '__init__'; chúng tôi có thể giúp bạn nếu bạn mô tả những gì bạn đang thực sự cố gắng thực hiện. –

Trả lời

67

__init__ là bắt buộc để trả lại Không. Bạn không thể (hoặc ít nhất là không nên) trả lại cái gì khác.

Hãy thử làm bất cứ điều gì bạn muốn trả về một biến mẫu (hoặc hàm).

>>> 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: Bạn ** không thể ** trả lại thứ gì khác. Nó không có ý nghĩa gì cả. –

+63

__init__ không trả về đối tượng mới được tạo ra - như đã thấy trong TypeError, nó được yêu cầu trả về None, phải không? Đối tượng mới được tạo ra được trả về bởi __new__, __init__ chỉ đặt một số thuộc tính của nó. Nhưng có, như bạn đã nói, thay đổi __init__, hoặc __new__, để trả lại một cái gì đó khác thực sự không có ý nghĩa. – weronika

+0

'Mới' ở đâu? Là 'mới' tiềm ẩn trong Python? Tôi cho rằng ngữ nghĩa của Python khác với Java và các ngôn ngữ khác sử dụng từ này. –

8

__init__ không trả lại bất cứ điều gì và phải luôn trả về None.

37

Từ 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.

Như một bằng chứng, mã này:

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

f = Foo() 

Cung cấp cho lỗi này:

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

Tại sao bạn sẽ muốn làm điều đó?

Nếu bạn muốn quay trở lại một số đối tượng khác khi một lớp được gọi, sau đó sử dụng __new__() phương pháp:

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

obj = MyClass() 
print obj 
+8

Vâng, __new__ là đúng cách để trả lại một thứ gì đó khác với một cá thể lớp khi sử dụng một lớp ... Tôi chỉ tự hỏi - có lý do nào bạn có thể thực sự muốn làm điều đó không? – weronika

+22

@weronika Một ý tưởng: trong bất kỳ tình huống nào bạn thường sử dụng một nhà máy, nhưng bạn có một số lý do muốn trình bày một giao diện trông giống như sự khởi tạo lớp bình thường. Ví dụ: khi thêm một số tham số tùy chọn mới vào '__init__' của lớp, bạn nhận ra rằng, để cung cấp tính linh hoạt mà bạn muốn, bạn cần một nhà máy lớp trả về các cá thể của các lớp con chuyên biệt. Nhưng người dùng thư viện của bạn đã sử dụng API hiện tại của bạn. Để bảo toàn nó, bạn ghi đè '__new__' để trả về các thể hiện của các lớp con chuyên biệt của bạn. –

+6

Nếu bạn muốn xem ví dụ về những gì Mark Amery đã nói, hãy kiểm tra mã nguồn của mô-đun 'datetime' từ Thư viện Chuẩn. Nó sử dụng '__new__' trong chính xác thời trang này. – Zearin

12

Phương pháp __init__, giống như các phương pháp và các chức năng khác trả về Không theo mặc định trong trường hợp không quay trở lại tuyên bố, vì vậy, bạn có thể viết như sau:

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

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

Nhưng, tất nhiên, thêm return None không mua cho bạn bất kỳ thứ gì.

Tôi không chắc chắn những gì bạn đang sau, nhưng bạn có thể quan tâm một trong những:

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

f=Foo() 
print f.value 
print f 

in:

42 
42 
+0

ohh..Tôi có thể truy cập biến thành viên trong lớp không? Sau đó, nên giải quyết vấn đề của tôi .... cảm ơn –

+0

@ lakshmipathi, Có, các biến mẫu như thế này là công khai. – quamrana

+0

Như là một oneliner để có được một cái gì đó có giá trị trả lại sau khi bắt đầu một lớp: 'f = Foo(). Value' – JLT

13

Sample Sử dụng các vấn đề trong câu hỏi có thể được như :

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) 

Tôi không có đủ danh tiếng nên không thể viết nhận xét, tôi s điên!Tôi ước gì có thể gửi nó như một bình luận cho weronika

+1

Điều này sẽ nâng cao một NameError: 'self' không được định nghĩa trong' __new __ (cls, Item) ' –

2

Chỉ muốn thêm, bạn có thể quay trở lại lớp học trong __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 

Các phương pháp trên sẽ giúp bạn thực hiện một hành động cụ thể khi một ngoại lệ trong thử nghiệm của bạn

+0

xin vui lòng xây dựng trên mã này. – nish

Các vấn đề liên quan