The consensus we've reached at work has mostly been that typing should really only be bothered to help users and devs where it's not clear what expected input and output is. Things like __init__ methods or other dunder methods are expected to return a certain type of object so they don't need it.
What I might recommend is typing your inputs a little more. As an example, explicitly use ints to represent timestamps, and use the function time.time_ns() for timestamps, then use structs to generate more accurate representations to hash.
classBlock:def__init__(self,data:Optional[List[Any]]=None,timestamp:Optional[float]=None,prevHash:Optional[bytes]=None):"""
Create a new block for the Blockchain
:param timestamp: Timestamp of the block, defaults to the time the block object is created
:param data: Data to store in the block, defaults to an empty list
:param prevHash: Hash of the previous block, defaults to None. Should always be specefied except for the genesis block.
"""ifdataisNone:self.data=[]else:self.data=dataiftimestampisNone:self.timestamp=time_ns()else:self.timestamp=timestampifprevHashisNone:self.prevHash=b''else:self.prevHash=prevHashself._hash=Noneself.nonce=0@propertydefhash(self)->bytes:"""
Return the (non-python) hash of the block
:return: The bytes of the hash of this block
"""ifself._hashisNone:hashFun=sha256()hashFun.update(self.prevHash)hashFun.update(struct.pack('@l',self.timestamp))hashFun.update(self.encode(self.data))hashFun.update(struct.pack('@l',self.nonce))self._hash=hashFun.hexdigest()returnself._hash
Here I've specified that data is a list of anything, timestamp is an int, and prevHash is bytes, and that Block.hash generates bytes. This informs a user/developer that's interfacing with it that this is what the methods are expecting to take or should be expected to return. The only thing I might also add for type hinting in the Block class is specifying the difficulty parameter in Block.mine() is an integer, as well as a check that it's greater than or equal to 1, raising an exception if it isn't.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Thanks @theflanman for your contribution. It is always cool to see code like yours to learn.
Do you think adding typing could be a good addition to your code? like:
Also I ♥ to see how you are using @property decorator in the example. I have prepared a small snippet to see the effect when using it:
I really like how you are using the iterator in the
__repr__
and other dunder methods.Have Fun!
The consensus we've reached at work has mostly been that typing should really only be bothered to help users and devs where it's not clear what expected input and output is. Things like
__init__
methods or other dunder methods are expected to return a certain type of object so they don't need it.What I might recommend is typing your inputs a little more. As an example, explicitly use ints to represent timestamps, and use the function time.time_ns() for timestamps, then use structs to generate more accurate representations to hash.
Here I've specified that data is a list of anything, timestamp is an int, and prevHash is bytes, and that Block.hash generates bytes. This informs a user/developer that's interfacing with it that this is what the methods are expecting to take or should be expected to return. The only thing I might also add for type hinting in the Block class is specifying the difficulty parameter in Block.mine() is an integer, as well as a check that it's greater than or equal to 1, raising an exception if it isn't.