[英]Pythonic way of computing optional instance variables when first called
我正在編寫一個 class 來表示來自航天器的一些數據,這些數據可以提供許多不同的數據產品,可用於計算其他變量。 加載每個變量的原始數據需要幾秒鍾的時間,因此每個變量只應在需要時加載,因為並非總是需要所有變量。
這是我的意思的最小工作示例:
class Spacecraft:
def __init__(self, time_range, configuration='default'):
self.time_range = time_range
# Initialise all possible variables to None
self.magnetometer = None
self.temperature = None
self.complicated_thing = None
# There are 30+ of these
def get_magnetometer(self):
self.magnetometer = self.load_data('magnetometer')
return self.magnetometer
def get_temperature(self):
self.temperature = self.load_data('temperature')
return self.temperature
def get_complicated_thing(self):
# Check each variable has a value
if self.temperature is None:
get_temperature()
if self.magnetometer is None:
get_magnetometer()
self.complicated_thing = self.temperature * self.magnetometer
return self.complicated_thing
# Plus more get_ functions for each instance variable
def load_data(self, product_name):
"""Loads raw 'product_name' data as np array.
"""
pass
# Use case 1: Only need limited number of parameters
only_need_magnetometer = Spacecraft('10:30-10:45')
plot(only_need_magnetometer.get_magnetometer())
# Use case 2: Need a different set of parameters
complicated_analysis = Spacecraft('10:45-11:00')
result = analysis(complicated_analysis.get_complicated_thing())
我不確定在__init__()
中將每個變量初始化為None
。 我也不喜歡計算派生變量的每個 function 開頭的冗長檢查。
有更好/更蟒蛇的方式嗎?
理想情況下,我想跳過初始化為None
並能夠將get_complicated_thing()
定義為:
def get_complicated_thing(self):
self.complicated_thing = self.temperature * self.magnetometer
return self.complicated_thing
如果self.temperature
或self.magnetometer
尚不存在,則會自動調用 getter,例如get_magnetometer()
。 然后可以將用例簡化為:
# Use case 1: Only need limited number of parameters
only_need_magnetometer = Spacecraft('10:30-10:45')
plot(only_need_magnetometer.magnetometer)
# Use case 2: Need a different set of parameters
complicated_analysis = Spacecraft('10:45-11:00')
result = analysis(complicated_analysis.complicated_thing)
至少對我來說,這更容易閱讀。
確實有一個可以使用的構造:property
。 有一些裝飾器允許為托管屬性定義getters
、 setters
和“析構函數”:
在您的情況下,您只需要吸氣劑:
class MyClass:
def __init__(self, *args, **kwargs):
# do stuff
@property
def magnometer(self):
# do heavy calculation/loading
return result
@property
def complicated_thing(self):
# we can access self.mangometer here (it will just run the magnometer bound function)
return self.magnometer*2
現在您說計算/加載操作很繁重。 可以很容易地緩存您的計算值,如下所示:
from functools import cache
...
@property
@cache
def myproperty(self):
return 42
...
但是請注意, cache
是在 3.9 中引入的,在 Python 3.8 中有一個cached_property
,您可以將其用作鏈式裝飾器的替代品。 或者,您可以按照該線程的內容編寫自己的緩存。
附加說明:在__init__
中將屬性設置為None
原則上沒有任何問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.