python - 如何在 Python 类型提示中说“此参数需要允许任意属性分配”?
问题描述
我有一个函数,其工作是将任意对象分配给目标对象的任意属性名称。如果tgt
quacks 像 a dict
(对不起,如果它是一个可变的 hashmap 类型的对象),它应该使用tgt[attrname] = obj
,否则它会调用setattr(tgt, attrname, obj)
. 我如何告诉 mypy 和类型系统我真正需要一个tgt
允许分配给任意名称的类型?
from typing import MutableMapping, Any, Union
def assignment_func(tgt : Union[MutableMapping, Any], attrname: str, obj: object):
"""
assign `obj` to `tgt` using the attrname.
setitem dict-type behavior takes precedence
"""
try:
if callable(getattr(tgt, "__getitem__", None)):
tgt[attrname] = obj
else:
setattr(tgt, attrname, obj)
print("yeehaa! worked with a %s" % (tgt.__class__.__name__))
except (Exception,) as e:
print("bummer, dinna work with a %s. got a %s" % (tgt.__class__.__name__, e.__class__.__name__))
class Foo:
pass
class BadSlot:
"""unknown `bar` will blow this up"""
__slots__ = "zoom"
class GoodSlot:
"""
works. but the attribute name can be anything
so, this, and anything with __slots___ should really be
flagged as a problem by mypy
"""
__slots__ = "bar"
#mypy should complain about list, object, GoodSlot and BadSlot
#Foo and a dict both support arbitrary assignments.
for tgt in [list(), dict(), object(), Foo(), GoodSlot(), BadSlot()]:
assignment_func(tgt, "bar", "coucou")
输出:
bummer, dinna work with a list. got a TypeError
yeehaa! worked with a dict
bummer, dinna work with a object. got a AttributeError
yeehaa! worked with a Foo
yeehaa! worked with a GoodSlot
bummer, dinna work with a BadSlot. got a AttributeError
mypy 有什么要说的?
没有什么。
但是如果将提示更改为
def assignment_func(tgt : Union[MutableMapping, object], attrname: str, obj: object):
然后它(正确地)提醒我object
不支持作业)。
error: Unsupported target for indexed assignment
,违规行处于tgt[attrname] = obj
MutableMapping 条件下。
Python版本:
有问题的代码是 2.7/3.6+ 代码,但让我们将其简化为仅适用于 3.6+。
tgt
是我在这里感兴趣的唯一论点。让我们假设attrname
已知是一个正确的属性名称(即attrname
不是类似的2badcantstartwithnumber
,但可能是toobadcantstartwithnumber
并且obj
没关系(Any
实际上我可能想使用它)。
我的代码中一个反复出现的错误来源是使用 SQLAlchemy 来获取只读数据。结果是一个可迭代的 ResultProxy,为了最大限度地减少 RAM 的使用,它没有__dict__
. 如果我打算将该 fetch 的行作为 tgt 传递给assignment_func,那么我需要记住包装/处理每一行,否则我会BadSlot
退出。 dict(row)
很好,但如果可能的话,我想提醒mypy
一下。Django ORM fetches 也有同样的问题。
解决方案
推荐阅读
- regex - 使用正则表达式将字符串转换为 JSON
- c# - 从 C# 重命名网页
- javascript - 具有 useContext() 的子项未使用当前值重新呈现
- python - 匹配所有内容,直到括号内有数字
- delphi - 如何检测窃取特定快捷方式的未知对象?
- java - 当 EditText 为空白并按下按钮时,Android 应用程序崩溃
- javascript - 在 React TypeScript 中键入输入的 keyup
- wcf - 无法在 ASP.NET Core 5.0 下的 IIS 中托管 CoreWcf
- angular - 我想将日期转换为 dd-mm-yyyy
- python - 尝试从 gstreamer appsink 获取 numpy 图像导致缓冲区太小错误