自定义一个向量

#from icecream import ic
import math
class Vector:
    #告诉解释器只有x,y两个变量,不会再有__dict__属性,节省内存
    __slots__ = ('__x','__y')
    # https://www.cnblogs.com/rainfd/p/slots.html
    
    def __init__(self,x,y):
        self.__x= float(x)
        self.__y= float(y)
    
    @property
    # https://www.liaoxuefeng.com/wiki/1016959663602400/1017502538658208
    def x(self):
        return self.__x
    @property
    def y(self):
        return self.__y
    # 对str提供支持   
    def __str__(self):
        return str(tuple(self))
    # 支持die dai
    def __iter__(self):
        return (i for i in (self.x,self.y))
    # 对 repr提供支持
    def __repr__(self):
        """
        return Vector(x,y)
        
        """
        return f'{type(self).__name__}({self.x},{self.y})'
    # 对 hash 提供支持
    # https://www.jianshu.com/p/4d3ef12eaf8e
    # 如果 object 属于可哈希对象,hash() 函数将返回其哈希值;如果 object 不属于可哈希对象,hash() 函数则会抛出异常。哈希值是一个整数。
    def __hash__(self):
        return hash(self.x)^hash(self.y)
    #对 abs 提供支持
    def __abs__(self):
        return math.hypot(self.x,self.y)
    # hypot() 返回欧几里德范数 sqrt(x*x + y*y)
    
    def __bool__(self):
        return bool(abs(self))

v1 = Vector(3, 4)
#调用print其实是隐形点用了对象的str方法
print(v1)

运行结果:

(3.0, 4.0)

继承父类:

#继承Vector类
class Vector2d(Vector):

    def __init__(self, x, y):
        super().__init__(x, y)
        self.__x = x
        self.__y = y
v2 = Vector2d(5, 6)
print(v2)

运行结果:

(5.0, 6.0)

受保护的属性和私有属性¶

单下划线开头 _x

双下划线开头 __y

单下划线结尾 class_, 防止和内置类型冲突
from array import array

print(array('d', list(range(20))))

运行结果:

array('d', [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0])

N 维 Vector

import math 
from array import array
import reprlib
from functools import reduce
class Vector:
    # N 维 Vector
    typecode = 'd' #浮点数8字节
    
    def __init__(self, components):
        self._components = array(self.typecode, components)
        # components 组件  typecode 数字类型:整型,浮点型
        
        #对str提供支持
    def __str__(self):
        return str(tuple(self))
    def __iter__(self):
        return (i for i in self._components)
        
        #对 repr提供支持
    def __repr__(self):
        '''
            return Vector([1.0, 2.0, 3.0...])
            
        '''
        components = reprlib.repr(self._components)
        #  实例aRepr的实例方法。功能类似内建方法repr(),不过可以对返回的字符串大小进行限制。
        components = components[components.find('['):-1]
        # find 如果包含指定索引值,返回的是索引值在字符串中的起始位置。如果不包含索引值,返回-1
        return f"{type(self).__name__}({components})"
        
    # 对hash 提供支持
    def __hash__(self):
        hash_list = map(lambda x: hash(x),self._components)
        return reduce(lambda a,b:a^b,hash_list,0)
    # reduce 有三个参数, 第三个参数是初始值的意思,是可有可无的参数。
    def __eq__(self,v):
        if len(self) != len(v):
            return False
        for a,b in zip(self,v):
            if a!=b:
                return False
        # return tuple(self) == tuple(v)
        # return len(self) == len(self) and all(a ==b for a,b in zip(self,v)) 
            
    #对abs提供支持
    def __abs__(self):
        return math.sqrt(sum(x*x for x in self._components))
        # 切片 https://www.jianshu.com/p/c48e6e903c38
    def __getitem__(self, index):
        cls = type(self)
        # type 与 isinstance 的区别
        # https://blog.csdn.net/LoveL_T/article/details/83104234
        if isinstance(index,slice):
            # https://www.jianshu.com/p/c48e6e903c38
            return cls(self._components[index])
        elif isinstance(index,int):
            return self._components[index]
        else :raise TypeError(f"{cls.__name__} indices(指数) must be integers.")
         
    # 运载符重载
    #+
    #https://www.cnblogs.com/lht-record/p/10306591.html
    def __add__(self, v):
        cls = type(self)
        return cls([x +y for x, y in itertools.zip_longest(self,v,fillvalue=0)])
        """
         def __add__(self, other):
        pairs = itertools.zip_longest(self, other, fillvalue=0)
        return Vector(a + b for a, b in pairs)
        #pairs是一个生成器,生成(a, b)形式元组,a来自self,b来自other,0填充
        """
    def __radd__(self,v):
        return self + v
        #__radd__是__add__的反向版本。
        #__radd__直接委托__add__
        
        # * scalar 乘以标量
    def __mul__(self ,scalar):
        cls = type(self)
        return cls([x*scalar for x in self])
    def __rmul__(self,scalar):
        return self*scalar
        
    #dot 点乘
    def __matmul__(self, v):
        cls = type(self)
        return sum([a*b for a,b in itertools.zip_longest(self,v,fillvalue=1)])
        
    def __rmatmul__(self,v):
        return self@v
    # 一个修饰符就是一个函数,它将被修饰的函数做为参数,并返回修饰后的同名函数或其它可调用的东西。
           
    @staticmethod
    def log():
        print ("ok")
            
      
  # staticmethod 返回函数的静态方法
        """
        class C(object):
            @staticmethod
            def f():
                print('runoob');
 
       C.f();          # 静态方法无需实例化
       cobj = C()
        cobj.f()        # 也可以实例化后调用
        """

多重继承与Mixin

Mixin 扩展类的功能

#Mixin 扩展类的功能
# https://blog.csdn.net/u012814856/article/details/81355935
import itertools
# class Plus:

#     def plus(self, v):
#         cls = type(self)
#         return cls([x + y for x, y in itertools.zip_longest(self, v, fillvalue=0)])

# class Minus:

#     def minus(self, v):
#         cls = type(self)
#         return cls([x - y for x, y in itertools.zip_longest(self, v, fillvalue=0)])

class CalculabilityMixin:
    # +
    def plus(self, v):
        cls = type(self)
        return cls([x + y for x, y in itertools.zip_longest(self, v, fillvalue=0)])

    # -
    def minus(self, v):
        cls = type(self)
        return cls([x - y for x, y in itertools.zip_longest(self, v, fillvalue=0)])

    # @
    def dot(self, v):
        cls = type(self)
        return sum([a * b for a, b in itertools.zip_longest(self, v, fillvalue=1)])


class LogMixin:

    def __getitem__(self, index):
        print(f"Getting value of index {index}.")
        return super().__getitem__(index)


class Vector2d(LogMixin, CalculabilityMixin, Vector):

    def __init__(self, *args):
        components = list(args) if len(args) > 1 else args[0]
        super().__init__(components)
        self._x = components[0]
        self._y = components[1]
v = Vector2d(1, 2)
print(v[0])

运行结果:

Getting value of index 0.
1.0
# 注意方法的搜索路径,不然容易产生错误
# 新类 宽度优先,旧类,深度优先
Vector2d.__mro__

运行结果:

(__main__.Vector2d, __main__.LogMixin, __main__.Vector, object)
v3 = Vector2d(1,2)
v4 = Vector2d(3,4)
print([3,4]+v3)
print(v3*10)
print(v3@[1,2])
print([1,2]@v3)
print(v3@v4)

运行结果:

Vector2d([4.0, 6.0])
Vector2d([10.0, 20.0])
5.0
5.0
11.0

1. 查官方文档 https://docs.python.org/3.6/¶

2. 直接Google 排名靠前的页面,尤其关注 Stackoverflow Google Python 风格指南 https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/contents/

def log():
    print('ok')


class Vector2d(Vector):

    def __init__(self, x, y):
        super().__init__([x, y])
        self._x = x
        self._y = y

    # https://blog.csdn.net/sinat_33718563/article/details/81298785
    @classmethod
    def build_from_other(cls, other_components):
        if isinstance(other_components, list):
            x, y = other_components
        return cls(x, y)


v = Vector2d(1, 2)
v.log()

运行结果:

ok

 

本文地址:https://blog.csdn.net/weixin_40959890/article/details/110466968