我正在尝试编写一个小的mixin类来桥接Set和MutableMapping类型:我希望映射类型能够接收一些对象(字节),对它们进行哈希处理并存储它们,以便它们可以访问哈希。
这是将此类与标准dict
混合使用的工作版本:
from hashlib import blake2b
class HashingMixin:
def add(self, content):
digest = blake2b(content).hexdigest()
self[digest] = content
class HashingDict(dict, HashingMixin):
pass
但是我不知道如何添加类型注释。
从https://github.com/python/mypy/issues/1996看来,mixin必须继承abc.ABC
和abc.abstractmethod
的子类,以定义它期望调用的所有方法,所以这是我的镜头:
import abc
from hashlib import blake2b
from typing import Dict
class HashingMixin(abc.ABC):
def add(self, content: bytes) -> None:
digest = blake2b(content).hexdigest()
self[digest] = content
@abc.abstractmethod
def __getitem__(self, key: str) -> bytes:
raise NotImplementedError
@abc.abstractmethod
def __setitem__(self, key: str, content: bytes) -> None:
raise NotImplementedError
class HashingDict(Dict[str, bytes], HashingMixin):
pass
然后Mypy抱怨HashingDict
的定义:
error: Definition of "__getitem__" in base class "dict" is incompatible with definition in base class "HashingMixin"
error: Definition of "__setitem__" in base class "dict" is incompatible with definition in base class "HashingMixin"
error: Definition of "__setitem__" in base class "MutableMapping" is incompatible with definition in base class "HashingMixin"
error: Definition of "__getitem__" in base class "Mapping" is incompatible with definition in base class "HashingMixin"
公开类型:
reveal_type(HashingMixin.__getitem__)
reveal_type(HashingDict.__getitem__)
产量:
error: Revealed type is 'def (coup.content.HashingMixin, builtins.str) -> builtins.bytes'
error: Revealed type is 'def (builtins.dict[_KT`1, _VT`2], _KT`1) -> _VT`2'
我不知道怎么了:(
答案 0 :(得分:1)
这似乎是mypy中的错误-请参阅mypy用于使用多重继承分析类的MRO的代码中的this TODO。简而言之,mypy会错误地完成忽略忽略您已使用具体值对Dict
进行参数化的功能,而是像在使用Dict
一样对代码进行分析。
我相信https://github.com/python/mypy/issues/5973可能是问题跟踪器中最相关的问题:根本原因是相同的。
在此错误修复之前,您可以通过在任何有错误的行上添加# type: ignore
来抑制mypy在该行上生成的错误。因此,您可以执行以下操作:
import abc
from hashlib import blake2b
from typing import Dict
class HashingMixin(abc.ABC):
def add(self, content: bytes) -> None:
digest = blake2b(content).hexdigest()
self[digest] = content
@abc.abstractmethod
def __getitem__(self, key: str) -> bytes:
raise NotImplementedError
@abc.abstractmethod
def __setitem__(self, key: str, content: bytes) -> None:
raise NotImplementedError
class HashingDict(Dict[str, bytes], HashingMixin): # type: ignore
pass
如果您决定采用这种方法,我建议您还留下一条注释,记录为什么您要抑制这些错误并使用--warn-unused-ignores
标志运行mypy。
前者是为了让您的代码的任何将来的读者受益;后者会在遇到# type: ignore
并没有实际抑制任何错误的Launching lib\main.dart on Android SDK built for x86 in debug mode...
Initializing gradle...
Resolving dependencies...
Running Gradle task 'assembleDebug'...
registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
Built build\app\outputs\apk\debug\app-debug.apk.
I/OpenGLRenderer( 5789): Davey! duration=865ms; Flags=1, IntendedVsync=2354083756924, Vsync=2354517090240, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=2354532725800, AnimationStart=2354532812780, PerformTraversalsStart=2354533033500, DrawStart=2354541099130, SyncQueued=2354542684770, SyncStart=2354683798150, IssueDrawCommandsStart=2354687158970, SwapBuffers=2354843953570, FrameCompleted=2355089974810, DequeueBufferDuration=52711000, QueueBufferDuration=687000,
Syncing files to device Android SDK built for x86...
I/oper.baby_name( 5789): The ClassLoaderContext is a special shared library.
I/chatty ( 5789): uid=10091(com.ruguethedeveloper.baby_names) FirestoreWorker identical 1 line
I/oper.baby_name( 5789): The ClassLoaderContext is a special shared library.
V/NativeCrypto( 5789): Registering com/google/android/gms/org/conscrypt/NativeCrypto's 284 native methods...
W/oper.baby_name( 5789): Accessing hidden method Ljava/security/spec/ECParameterSpec;->getCurveName()Ljava/lang/String; (light greylist, reflection)
D/NetworkSecurityConfig( 5789): No Network Security Config specified, using platform default
I/ProviderInstaller( 5789): Installed default security provider GmsCore_OpenSSL
W/oper.baby_name( 5789): Accessing hidden field Ljava/nio/Buffer;->address:J (light greylist, reflection)
W/ManagedChannelImpl( 5789): [{0}] Failed to resolve name. status={1}
W/Firestore( 5789): (18.2.0) [OnlineStateTracker]: Could not reach Cloud Firestore backend. Connection failed 1 times. Most recent error: Status{code=UNAVAILABLE, description=Unable to resolve host firestore.googleapis.com, cause=java.lang.RuntimeException: java.net.UnknownHostException: Unable to resolve host "firestore.googleapis.com": No address associated with hostname
W/Firestore( 5789): at io.grpc.internal.DnsNameResolver.resolveAll(DnsNameResolver.java:331)
W/Firestore( 5789): at io.grpc.internal.DnsNameResolver$1.run(DnsNameResolver.java:214)
W/Firestore( 5789): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
W/Firestore( 5789): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
W/Firestore( 5789): at java.lang.Thread.run(Thread.java:764)
W/Firestore( 5789): Caused by: java.net.UnknownHostException: Unable to resolve host "firestore.googleapis.com": No address associated with hostname
W/Firestore( 5789): at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:157)
W/Firestore( 5789): at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:105)
W/Firestore( 5789): at java.net.InetAddress.getAllByName(InetAddress.java:1154)
W/Firestore( 5789): at io.grpc.internal.DnsNameResolver$JdkAddressResolver.resolveAddress(DnsNameResolver.java:517)
W/Firestore( 5789): at io.grpc.internal.DnsNameResolver.resolveAll(DnsNameResolver.java:299)
W/Firestore( 5789): ... 4 more
W/Firestore( 5789): Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)
W/Firestore( 5789): at libcore.io.Linux.android_getaddrinfo(Native Method)
W/Firestore( 5789): at libcore.io.BlockGuardOs.android_getaddrinfo(BlockGuardOs.java:172)
W/Firestore( 5789): at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:137)
W/Firestore( 5789): ... 8 more
W/Firestore( 5789): }
W/Firestore( 5789): This typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend.
D/ ( 5789): HostConnection::get() New Host Connection established 0xee548e00, tid 5814
D/EGL_emulation( 5789): eglMakeCurrent: 0xee545c00: ver 3 0 (tinfo 0xd739def0)
D/skia ( 5789): Program linking failed.
I/chatty ( 5789): uid=10091(com.ruguethedeveloper.baby_names) 1.gpu identical 7 lines
D/skia ( 5789): Program linking failed.
W/ManagedChannelImpl( 5789): [{0}] Failed to resolve name. status={1}
W/ManagedChannelImpl( 5789): [{0}] Failed to resolve name. status={1}
W/ManagedChannelImpl( 5789): [{0}] Failed to resolve name. status={1}
W/ManagedChannelImpl( 5789): [{0}] Failed to resolve name. status={1}
W/ManagedChannelImpl( 5789): [{0}] Failed to resolve name. status={1}
时使mypy报告警告。
(当然,您总是可以自己动手进行修复!)