欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python高级编程

程序员文章站 2022-03-23 11:24:43
自定义一个向量#from icecream import icimport mathclass 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.__...

自定义一个向量

#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 排名靠前的页面,尤其关注 * 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