Python Style objects
Take a two-element vector object as an example
Import mathfrom Array import arrayclass vector2d:typecode = ' d ' def __init__ (self, x, y): self.x = float (x) Self.y = Float (y) def __iter__ (self): # makes the vector2d into an iterative object # The implementation of the __iter__ method enables the class to be converted to a tuple, among other iterative classes Return (I for I in (self.x, SELF.Y)) def __repr__ (self): class_name = Type (self). __name__ # type (self): <class ' __main__. Vector2d ' > Return ' {} ({!r},{!r}) '. Format (class_name, *self) def __str__ (self): return str (tuple) def __eq__ (self, Other): Return tuple (self) = = Tuple (other) def __abs__ (self): return Math.hypot . x, SELF.Y) def __bool__ (self): return bool (self) def __bytes__ (self): "" To process the Vector2d object as a binary sequence, format I Custom "" "# d:double Type Array return (bytes ([Ord (Self.typecode)]) + bytes (Array (Self.typecode, self)) # ————— Alternate destructor method —————— @classmethod # class method, CLS represents the class itself Def frombytes (CLS, octets): "" "corresponds to the method above, where a new destructor is created, using the A specific twoThe binary sequence constructs the Vector2d class instance "" "TypeCode = Chr (octets[0]) Memv = Memoryview (octets[1:]). CAST (TypeCode) return cl S (*MEMV) # class name (parameter), visible, class method commonly used as an alternate destructor #-formatted output-def angle (self): # Math.atan (scope) input as Tan value # math.atan2 (Y, x) input is the corresponding vector coordinate (starting point is Origin) return math.atan2 (Self.y, self.x) def __format__ (self, fmt_spec= "):" "" Format the output if the end of the format is P Output polar coordinates, enter other formats as digital formats, and an input format specified to two numbers, such as:. 3ep "" "If Fmt_spec.endswith (' P '): Fmt_spec = fmt_spec[:-1] coords = (ABS (self), self.angle ()) out_fmt = ' <{}, {}> ' else:coords = self Out_fmt = ' ({}, {}) ' Components = (format (c, Fmt_spec) as C in coords) return Out_fmt.format (*co mponents)
This object supports most Python operations at this point,
if __name__ = = ' __main__ ': b = Bytes (vector2d (3, 4)) print ( vector2d.frombytes (b)) Print (Format (vector2d ( 1, 1), '. 5fp ')
(3.0, 4.0)
<1.41421, 0.78540>
But an important method is still not able to achieve, __hash__, this is related to whether the object can be stored in the dictionary for high-speed read properties, can actually hash the object requires three conditions:
Need __hash__ method
Requires __eq__ method (already implemented)
the hash value of an instance of an object that needs to be immutable is related to how the lookup is used, and must never be changed
That is, we specify that V.x=1 (V is a class instance) will give an error, which requires some other action:
Class vector2d: typecode = ' d ' def __init__ (self, x, y): self.__x = float (x) self.__y = float (y) @ Property def x (self): return self.__x @property def y (self): return self.__y def __ Hash__ (self): return Hash (self.x) ^ hash (self.y)
Other methods do not need to be modified,
V1 = vector2d (3, 4)
V2 = vector2d (3.1, 4.2)
Print (hash (v1), hash (v2))
# 7 384307168202284039
Class methods and Static methods
#-comparison class method and static method-class Demo: @classmethod def klassmeth (*args): return args @ staticmethod def Statmeth (*args): return args def normal (*args): return args
Unlike instance methods, the first parameter of a class method is always the class itself, so it is often used for alternate destructors, and static methods do not have the default first parameter, which is tested as follows:
Print (Demo.klassmeth ("Hello"))
Print (Demo.statmeth ("Hello"))
Demo = Demo ()
Print (Demo.normal ("Hello"))
# (<class ' __main__. Demo ';, ' hello ')
# (' Hello ',)
# (<__main__. Demo object at 0x000000000289f978>, ' hello ')
"Fluent Python" chapter 9th _ Python-style objects