python--位运算



class Bit():
    def __init__(self,word:int):
        '''
        :param word: 0-65535
        '''
        self.word = word
    
    

    def get(self,postion:int)->bool:
        w = self.word & 1 << postion
        return bool(w)

    def write(self,postion:int,value:bool)->None:
        '''
        :param postion: 位索引 范围0-15
        :param value: True or False
        :return: None
        '''
        if value:
            self.word = self.word | 1 << postion
        else:
            self.word = self.word & ~1 << postion

    def __str__(self):
        return f'十进制:{self.word},   二进制:{bin(self.word)[2:].zfill(16)}'

在上位机开发中,经常要进行位运算。一般通过通讯协议从下位机(plc ,仪器,仪表,传感器等)接受数据,数据一般都是整形数据,范围为(0-65535)。这时在上位机就要对这些数据进行解析到某个位,然后就可以对这个位进行读写操作。这里给出对一个16位的数据进行了封装,代码虽然冗余,但容易理解。后期在对代码进行优化,加入装饰器及魔法方法,那样代码就简洁了。


class IntToBit(object):
    #获取或设置一个字(16位整数)的位状态

    def __init__(self,world:int):
        if not isinstance(world,int):
            raise StopIteration('数据类型错误')
        if world<0 or world>65535:
            raise StopIteration('数据小于0或大于65535')
        self.world=world
    def __str__(self):print(bin(self.world))
    def _get_0(self):return bin(self.world & 0x0001)
    def _get_1(self):return bin(self.world & 0x0002)
    def _get_2(self):return bin(self.world & 0x0004)
    def _get_3(self):return bin(self.world & 0x0008)
    def _get_4(self):return bin(self.world & 0x0010)
    def _get_5(self):return bin(self.world & 0x0020)
    def _get_6(self):return bin(self.world & 0x0040)
    def _get_7(self):return bin(self.world & 0x0080)
    def _get_8(self):return bin(self.world & 0x0100)
    def _get_9(self):return bin(self.world & 0x0200)
    def _get_10(self):return bin(self.world & 0x0400)
    def _get_11(self):return bin(self.world & 0x0800)
    def _get_12(self):return bin(self.world & 0x1000)
    def _get_13(self):return bin(self.world & 0x2000)
    def _get_14(self):return bin(self.world & 0x4000)
    def _get_15(self):return bin(self.world & 0x8000)
    def _set_0(self,num:bool):
        if not isinstance(num,bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0001
        else:
            self.world = self.world & 0xfffe

    def _set_1(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0002
        else:
            self.world = self.world & 0xfffd


    def _set_2(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0004
        else:
            self.world = self.world & 0xfffb


    def _set_3(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0008
        else:
            self.world = self.world & 0xfff7

    def _set_4(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0010
        else:
            self.world = self.world & 0xffef

    def _set_5(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0020
        else:
            self.world = self.world & 0xffdf

    def _set_6(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0040
        else:
            self.world = self.world & 0xffbf

    def _set_7(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0080
        else:
            self.world = self.world & 0xff7f

    def _set_8(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0100
        else:
            self.world = self.world & 0xfeff

    def _set_9(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0200
        else:
            self.world = self.world & 0xfdff

    def _set_10(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0400
        else:
            self.world = self.world & 0xfbff

    def _set_11(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x0800
        else:
            self.world = self.world & 0xf7ff

    def _set_12(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x1000
        else:
            self.world = self.world & 0xefff

    def _set_13(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x2000
        else:
            self.world = self.world & 0xdfff

    def _set_14(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x4000
        else:
            self.world = self.world & 0xdfff

    def _set_15(self, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | 0x8000
        else:
            self.world = self.world & 0x7fff

    _0=property(_get_0,_set_0)
    _1=property(_get_1,_set_1)
    _2=property(_get_2,_set_2)
    _3=property(_get_3,_set_3)
    _4=property(_get_4,_set_4)
    _5=property(_get_5,_set_5)
    _6=property(_get_6,_set_6)
    _7=property(_get_7,_set_7)
    _8=property(_get_8,_set_8)
    _9=property(_get_9,_set_9)
    _10=property(_get_10,_set_10)
    _11=property(_get_11,_set_11)
    _12=property(_get_12,_set_12)
    _13=property(_get_13,_set_13)
    _14=property(_get_14,_set_14)
    _15=property(_get_15,_set_15)

if __name__=='__main__':
    #测试代码

    # 20=10100=0x14

    v=IntToBit(20) #创建以个对象,这里传入的数据为20


    #显示数据当前状态
    print(v)
    # 0b10100


    #查询第1位的状态
    print(v._0)
    #0b0

    #将第一位状态设置为True
    v._0=True
    print(v._0)
    #0b1

    #查看当前字状态
    print(v)
    #0b10101

    #将第16位设位True
    v._15=True
    print(v._15)
    #0b1000000000000000

    print(v)
    #0b1000000000010101

网上对位运算的案例比较少,理解起来一般比较肤浅。经过一位高才生的修改,上面代码瞬间优化了很多。对位的处理也有了深刻理解。位运算中左移和右移比较有意思,先解释下概念,N<



class IntToBit(object):
    # 获取或设置一个字(16位整数)的位状态

    def __init__(self, world: int):
        if not isinstance(world, int):
            raise StopIteration('数据类型错误')
        if world < 0 or world > 65535:
            raise StopIteration('数据小于0或大于65535')
        self.world = world

    def __str__(self): return (str(bin(self.world)))

    def get(self, flag: int):
        return bin(self.world & (1 << flag))

    def set(self, flag: int, num: bool):
        if not isinstance(num, bool):
            raise StopIteration('数据类型不是布尔')
        if num:
            self.world = self.world | (1 << flag)
        else:
            self.world = self.world & (65535 - (1 << flag))

    # def _get_0(self): return bin(self.world & 0x0001)
    # def _get_1(self): return bin(self.world & 0x0002)
    # def _get_2(self): return bin(self.world & 0x0004)
    # def _get_3(self): return bin(self.world & 0x0008)
    # def _get_4(self): return bin(self.world & 0x0010)
    # def _get_5(self): return bin(self.world & 0x0020)
    # def _get_6(self): return bin(self.world & 0x0040)
    # def _get_7(self): return bin(self.world & 0x0080)
    # def _get_8(self): return bin(self.world & 0x0100)
    # def _get_9(self): return bin(self.world & 0x0200)
    # def _get_10(self): return bin(self.world & 0x0400)
    # def _get_11(self): return bin(self.world & 0x0800)
    # def _get_12(self): return bin(self.world & 0x1000)
    # def _get_13(self): return bin(self.world & 0x2000)
    # def _get_14(self): return bin(self.world & 0x4000)
    # def _get_15(self): return bin(self.world & 0x8000)

    # def _set_0(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0001
    #     else:
    #         self.world = self.world & 0xfffe

    # def _set_1(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0002
    #     else:
    #         self.world = self.world & 0xfffd

    # def _set_2(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0004
    #     else:
    #         self.world = self.world & 0xfffb

    # def _set_3(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0008
    #     else:
    #         self.world = self.world & 0xfff7

    # def _set_4(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0010
    #     else:
    #         self.world = self.world & 0xffef

    # def _set_5(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0020
    #     else:
    #         self.world = self.world & 0xffdf

    # def _set_6(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0040
    #     else:
    #         self.world = self.world & 0xffbf

    # def _set_7(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0080
    #     else:
    #         self.world = self.world & 0xff7f

    # def _set_8(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0100
    #     else:
    #         self.world = self.world & 0xfeff

    # def _set_9(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0200
    #     else:
    #         self.world = self.world & 0xfdff

    # def _set_10(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0400
    #     else:
    #         self.world = self.world & 0xfbff

    # def _set_11(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x0800
    #     else:
    #         self.world = self.world & 0xf7ff

    # def _set_12(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x1000
    #     else:
    #         self.world = self.world & 0xefff

    # def _set_13(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x2000
    #     else:
    #         self.world = self.world & 0xdfff

    # def _set_14(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x4000
    #     else:
    #         self.world = self.world & 0xdfff

    # def _set_15(self, num: bool):
    #     if not isinstance(num, bool):
    #         raise StopIteration('数据类型不是布尔')
    #     if num:
    #         self.world = self.world | 0x8000
    #     else:
    #         self.world = self.world & 0x7fff

    #_value = property(_get, _set)

    # _0 = property(_get_0, _set_0)
    # _1 = property(_get_1, _set_1)
    # _2 = property(_get_2, _set_2)
    # _3 = property(_get_3, _set_3)
    # _4 = property(_get_4, _set_4)
    # _5 = property(_get_5, _set_5)
    # _6 = property(_get_6, _set_6)
    # _7 = property(_get_7, _set_7)
    # _8 = property(_get_8, _set_8)
    # _9 = property(_get_9, _set_9)
    # _10 = property(_get_10, _set_10)
    # _11 = property(_get_11, _set_11)
    # _12 = property(_get_12, _set_12)
    # _13 = property(_get_13, _set_13)
    # _14 = property(_get_14, _set_14)
    # _15 = property(_get_15, _set_15)




上面的代码有个错误,proprety属性时,不能对fget()方法传参数只好去调用 类方法。不过可以用魔法方法实现这个功能。



class IntToBit(object):

    def __init__(self,word:int):
        if not isinstance(word,int):
            raise StopIteration('数据类型不对')
        if word<0 or word>65535:
            raise StopIteration("数字不在范围")
        self.word=word

    def __getitem__(self, key):
        if not isinstance(key, int):
            raise StopIteration('数据类型错误')
        if (key<0) or (key > 16):
            raise StopIteration("数字不在范围")
        return bin(self.word & (1<16):
            raise StopIteration("数字不在范围")

        if value==True:
            self.word=self.word | (1<

把上面代码再一次优化,加入装饰器和断言


class IntToBit:

    def __check_init(func):
        def inner(self,value):
            if not isinstance(value,int):
                raise StopIteration("数据类型不匹配")
            return func(self,value)
        return inner

    @__check_init
    def __init__(self,v:int):
        assert 0<=v<=65535,"超出范围"
        self.v = v

    def __str__(self):
        return "{} 的二进制数为0b: {}".format(self.v,bin(self.v))

    __repr__=__str__

    @__check_init
    def __getitem__(self, index):
        assert 0<=index<=15,"超出范围,应为0-15之间"
        return bin(self.v & (1<

对上面代码再次处理,如何生成不同的装饰器在去装饰不同的函数,本例中加入要对函数里的参数类型,数据范围进行限制,比如f1(x,y,z)要求x 为int,y=0,z=100, f2(x,y,z)要求x为str,y=10,z=20等等,那怎么办呢?要么对没一个函数分别写一个装饰器,还有一个方法就是在创建一个函数,这个函数的功能就是生成不同的装饰器,然后再用该装饰器去装饰不同的函数。这里面确实很绕,也是装饰器最难以理解的地方。我也是想了好久,才明白。其实这样写代码比较晦涩,实际很少这样用吧


class IntToBit:

    def __getzsq(type,min,max):
        '''
        生成不同装饰器
        :param type: 数据类型
        :param min: 数据最小值
        :param max: 数据最大值
        :return: 返回装饰器
        '''
        def check_init(func):
            def inner(self, value):
                if not isinstance(value, type):
                    raise StopIteration("数据类型不匹配")
                if valuemax:
                    raise "数据超出范围"
                return func(self, value)
            return inner
        return check_init  #返回装饰器

    @__getzsq(int,0,65535)
    def __init__(self,v:int):
        self.v = v

    def __str__(self):
        return "{} 的二进制数为0b: {}".format(self.v,bin(self.v))

    __repr__=__str__

    @__getzsq(int,0,15)
    def __getitem__(self, index):
        return bin(self.v & (1<

优化数字数字显示,


class IntToBit:

    def __getzsq(type,min,max):
        '''
        生成不同装饰器
        :param type: 数据类型
        :param min: 数据最小值
        :param max: 数据最大值
        :return: 返回装饰器
        '''
        def check_init(func):
            def inner(self, value):
                if not isinstance(value, type):
                    raise StopIteration("数据类型不匹配")
                if valuemax:
                    raise "数据超出范围"
                return func(self, value)
            return inner
        return check_init  #返回装饰器

    @__getzsq(int,0,65535)
    def __init__(self,v:int):
        self.v = v

    def __str__(self):
        x = "{:0>16}".format(str(bin(self.v))[2:]) #显示16个位的字符串,不够的用0填充
        x0 = x[0:4]
        x1 = x[4:8]
        x2 = x[8:12]
        x3 = x[12:16]

        return "{} 的二进制数为0b: {}_{}_{}_{}".format(self.v,x0,x1,x2,x3)

    __repr__=__str__

    @__getzsq(int,0,15)
    def __getitem__(self, index):
        return bin(self.v & (1<

modbus通讯,数据类型转换

word = 0b1111_1001

def f(n):
    global word
    w= word & 1<None:
    global word
    if value:
        w = word | 1<

import struct

def ReadFloat(*args,reverse=False):
    for n,m in args:
        n,m = '%04x'%n,'%04x'%m
    if reverse:
        v = n + m
    else:
        v = m + n
    y_bytes = bytes.fromhex(v)
    y = struct.unpack('!f',y_bytes)[0]
    y = round(y,6)
    return y

def WriteFloat(value,reverse=False):
    y_bytes = struct.pack('!f',value)
    # y_hex = bytes.hex(y_bytes)
    y_hex = ''.join(['%02x' % i for i in y_bytes])
    n,m = y_hex[:-4],y_hex[-4:]
    n,m = int(n,16),int(m,16)
    if reverse:
        v = [n,m]
    else:
        v = [m,n]
    return v

def ReadDint(*args,reverse=False):
    for n,m in args:
        n,m = '%04x'%n,'%04x'%m
    if reverse:
        v = n + m
    else:
        v = m + n
    y_bytes = bytes.fromhex(v)
    y = struct.unpack('!i',y_bytes)[0]
    return y

def WriteDint(value,reverse=False):
    y_bytes = struct.pack('!i',value)
    # y_hex = bytes.hex(y_bytes)
    y_hex = ''.join(['%02x' % i for i in y_bytes])
    n,m = y_hex[:-4],y_hex[-4:]
    n,m = int(n,16),int(m,16)
    if reverse:
        v = [n,m]
    else:
        v = [m,n]
    return v

if __name__ == "__main__":
    # print(ReadFloat((62915,16456 )))

    # print(WriteFloat(3.16))
    print(ReadDint((94,14)))
    # print(WriteDint(456787654))


你可能感兴趣的:(python基础学习,python,pyqt)