选项 1:在 try 中分配
选项 2:在 try 中分配
选项 3:在实例函数中分配
选项 4:在初始化
我有一个类字段,我想将依赖项调用的结果分配给它。 执行依赖项调用、对服务器的 HTTP 调用并分配结果的最佳位置在哪里?
以这个类为例:
@dataclass
class User:
id: str
username: str = "" # Unknown at initialization stage, requires http call to get username based in id
在这种情况下:
user = User(id='12345')
result = dummy_library.get_username(user.id) # call to a server and return result
user.username = result.username
我有几个选项,但是,我无法决定使用哪一个:
选项 1:在 try 中分配username
/在__init__
中除外
优点:
- 简单
缺点:
- 很难测试,需要将
dummy_library
注入课堂才能调用
选项 2:在 try 中分配username
/在__post_init__
中除外
与选项 1 相同,但将工作转移到post_init
选项 3:在实例函数中分配username
class User:
...
def set_username(self, dummy_library):
try:
result = dummy_library.get_username(user.id) # call to a server and return result
user.username = result.username
except:
...
...
user = User(id='12345')
user.set_username(dummy_library)
优点:
- 通过依赖注入轻松进行单元测试
缺点:
- 冗余,必须在每次
User
实例化后调用set_username
选项 4:在初始化User
之前获取username
try:
user_id = '12345'
result = dummy_library.get_username(id=user_id) # call to a server and return result
user = User(id=user_id, username=result.username)
except:
...
优点:
- 通过依赖注入轻松进行单元测试
缺点:
- 冗余,尝试/除了每个用户实例化
将username
设为属性并为其指定默认值。
class User:
def __init__(self, id_, dummy_library, username=None):
self.id = id_
self._username = username
self._dummy_library = dummy_library
@property
def username(self):
if self._username is None:
try:
self._username = self._dummy_library.get_username(self.id)
except:
print('error')
return self._username
u = User(42, dummy_library)
print(u.username)
优点:
- 所有用户名获取逻辑都在一个地方
- 可以通过传递修补/假
dummy_library
(或实际传递username
(来轻松测试User
- API 调用会延迟到我们第一次尝试访问
.username
,并且只执行一次(除非username
明确设置为None
(。
请注意,资源库未实现,但如果需要其他逻辑,则可以实现。