2017-02-13 37 views
5

Tôi đang cố gắng triển khai thuộc tính lười biếng. Say, một đối tượng là khởi tạo bởi object._x = None, và sau đó tôi muốn viết một cái gì đópython: câu lệnh có thể là biểu thức bên trong?

@property 
def x(self): 
    return self._x or (init_x_value(); x) 

để initializer được gọi là chỉ lần đầu tiên các thuộc tính được nhìn lên.

Trong scala, một biểu thức có thể chứa câu lệnh. Là một cái gì đó tương tự có thể trong python. Nếu không, có cách nào khác để thực hiện nó hay tôi nên gắn bó với if-else?

+0

'init_x_value' trả về' None' phải không? –

+1

Theo như tôi biết điều này không thể được thực hiện, đó là một trong những lý do 'lambda' rất hạn chế trong Python. – melpomene

+0

@WillemVanOnsem: có thể, chỉ tính giá trị '_x' và lưu nó vào đối tượng –

Trả lời

6

Nếu init_x_valuelợi nhuận None, bạn có thể chỉ cần sử dụng:

return self._x or init_x_value() or self._x 

Lưu ý tuy nhiên, giống như @3Doubloons nói trong bình luận của họ, rằng nếu self._x là một cái gì đó sai-ish như None, [] (một sản phẩm nào danh sách), () một bộ trống hoặc một lớp đã ghi đè phương thức __bool__, nó sẽ chuyển sang phương thức init có thể tốn kém tính toán.

Trong trường hợp init_x_valuetrả về tính x giá trị bản thân, thậm chí bạn có thể viết nó thích:

return self._x or init_x_value() 

Điều này là do or bằng Python là khá đặc biệt: các x or y công trình như:

if bool(x): 
    return x 
else: 
    return y 

xy được tạo lazily. Vì bool(None)False trong trường hợp đầu tiên, do đó, nó sẽ kiểm tra self._x. Nếu self._xNone, nó sẽ tiếp tục bằng cách gọi init_x_value() vì phương thức đó không trả về bất kỳ thứ gì mà nó trả về hoàn toàn None, cũng không được chấp nhận bởi chuỗi or hoặc, do đó cuối cùng nó sẽ được giải quyết thành self._x vừa qua.

+0

Đẹp, không xảy ra với tôi để sử dụng gấp đôi 'hoặc'. Tuy nhiên, nếu muốn có một tuyên bố và không phải là một cuộc gọi chức năng, không có cách nào nó có thể được thực hiện, phải không ?? –

+0

@blue_note: không xa như tôi biết, vì bài tập không có kết quả (nó không trả lại bất cứ điều gì). –

+0

Bạn cần phải cẩn thận với cách tiếp cận này. Nếu 'self._x' là falsey,' init_x_values' sẽ được gọi mỗi lần. – 3Doubloons

5

Để trả lời câu hỏi tiêu đề: không, trong Python, một biểu thức không thể chứa câu lệnh. giai đoạn.

Cách pythonic thích hợp để viết getter của bạn là:

@property 
def x(self): 
    # assume _x defaults to None 
    if self._x is None: 
     # here you can have has many statements as 
     # you like ;) 
     self._x = init_x_value() 
    return self._x 

có thể không nhìn thông minh như ba 'hoặc' hoặc báo cáo nội tuyến hoặc bất cứ điều gì nhưng nó cũng đơn giản, đơn giản, rõ ràng và có thể đọc được vì nó có thể.

1

Bạn có thể ẩn những điều khoản trong một chức năng:

@property 
def x(self): 
    def initialize_and_return_x(): 
     init_x_value() 
     return self._x 
    return self._x or initialize_and_return_x() 
Các vấn đề liên quan