首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Python 3中模拟4位整数?

如何在Python 3中模拟4位整数?
EN

Stack Overflow用户
提问于 2014-05-17 08:55:56
回答 3查看 5.3K关注 0票数 1

我想模拟无符号4位整数的溢出行为,如下所示:

代码语言:javascript
复制
>>> x, y = Int4(10), Int4(9)
>>> x + y
Int4(3)
>>> x * y
Int4(10)

内建int的继承似乎有效。是否可以实现Int4类而不覆盖__add__之类的运算符方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-05-17 09:00:29

不,子类int在应用算术时不会自动重复使用该类型:

代码语言:javascript
复制
>>> class Int4(int):
...     def __new__(cls, i):
...         return super(Int4, cls).__new__(cls, i & 0xf)
... 
>>> x, y = Int4(10), Int4(9)
>>> x + y
19
>>> type(x + y)
<type 'int'>

您必须重写__add__等方法,以便在执行此操作时将其转换为Int4()

如果您只想支持类型本身(例如,不支持转换进程中的其他数值类型),那么您可以生成其中的大多数:

代码语言:javascript
复制
from functools import wraps

class Int4(int):
    def __new__(cls, i):
        return super(Int4, cls).__new__(cls, i & 0xf)

def add_special_method(cls, name):
    mname = '__{}__'.format(name)
    @wraps(getattr(cls, mname))
    def convert_to_cls(self, other):
        bound_original = getattr(super(cls, self), mname)
        return type(self)(bound_original(other))
    setattr(cls, mname, convert_to_cls)

for m in ('add', 'sub', 'mul', 'floordiv', 'mod', 'pow',
          'lshift', 'rshift', 'and', 'xor', 'or'):
    add_special_method(Int4, m)
    add_special_method(Int4, 'r' + m)  # reverse operation

这将生成总是从算术特殊方法返回self类型的方法;这也将允许对Int4进行进一步的子类划分。

演示:

代码语言:javascript
复制
>>> from functools import wraps
>>> class Int4(int):
...     def __new__(cls, i):
...         return super(Int4, cls).__new__(cls, i & 0xf)
... 
>>> def add_special_method(cls, name):
...     mname = '__{}__'.format(name)
...     @wraps(getattr(cls, mname))
...     def convert_to_cls(self, other):
...         bound_original = getattr(super(cls, self), mname)
...         return type(self)(bound_original(other))
...     setattr(cls, mname, convert_to_cls)
... 
>>> for m in ('add', 'sub', 'mul', 'floordiv', 'mod', 'pow',
...           'lshift', 'rshift', 'and', 'xor', 'or'):
...     add_special_method(Int4, m)
...     add_special_method(Int4, 'r' + m)  # reverse operation
... 
>>> x, y = Int4(10), Int4(9)
>>> x + y
3
>>> x * y
10
票数 6
EN

Stack Overflow用户

发布于 2014-05-17 09:24:51

重写__add__方法是个好主意,因为您可以使计算看起来很清楚。Int4(4) + Int4(7)看起来比Int4(4).addTo(Int4(7))好(或者类似的东西)。下面是可以帮助您的代码:

代码语言:javascript
复制
class Int4:
  def __init__(self, num): # initialising
    self.num = self.cap(num)

  def __str__(self):
    return str(self.num)

  def __repr__(self):
    return "Int4(" + self.__str__() + ")"

  def __add__(self, other): # addition
    return Int4(self.cap(self.num + other.num))

  def __sub__(self, other): # subtraction
    return Int4(self.cap(self.num - other.num))

  @staticmethod
  def cap(num): # a method that handles an overflow
    while num < 0:
      num += 16
    while num >= 16:
      num -= 16
    return num

并测试:

代码语言:javascript
复制
>>> x,y,z = Int4(5), Int4(8), Int4(12)
>>> x
Int4(5)
>>> y
Int4(8)
>>> z
Int4(12)
>>> print x+y
13
>>> print z+y
4
>>> print x-z
9
票数 1
EN

Stack Overflow用户

发布于 2015-06-11 21:46:24

这并不像@martijn的answer那样聪明,但它似乎适用于python2.7和3.*,而我在python2.7上得到了这个答案。

代码语言:javascript
复制
import sys

lt_py3 = sys.version_info < (3,)
lt_py33 = sys.version_info < (3, 3)


class Int(int):
    '''
    int types
    '''
    def __new__(self, val=0):
        return int.__new__(self, val & (1 << self.bits - 1) - 1)

    def __max_type_bits(self, other):
        '''
        determine the largest type and bits available from those in `self` and
        `other`
        '''
        if hasattr(other, 'bits'):
            if self.bits < other.bits:
                return type(other), other.bits
        return type(self), self.bits

    def __unary_typed(oper):
        '''
        return a function that redefines the operation `oper` such that the
        result conforms to the type of `self`
        '''
        def operate(self):
            return type(self)(oper(self))
        return operate

    def __typed(oper):
        '''
        return a function that redefines the operation `oper` such that the
        result conforms to the type of `self` or `other`, whichever is larger
        if both are strongly typed (have a `bits` attribute); otherwise return
        the result conforming to the type of `self`
        '''
        def operate(self, other):
            typ, bits = self.__max_type_bits(other)
            return typ(oper(self, other))
        return operate

    def __unary_ranged(oper):
        '''
        return a function that redefines the operator `oper` such that the
        result conforms to both the range and the type of `self`
        '''
        def operate(self, other):
            '''
            type and bitmask the result to `self`
            '''
            return type(self)(oper(self) & (1 << self.bits - 1) - 1)
        return operate

    def __ranged(oper):
        '''
        return a function that redefines the operator `oper` such that the
        result conforms to both the range and the type of `self` or `other`,
        whichever is larger if both are strongly typed (have a `bits`
        attribute); otherwise return the result conforming to the type of
        `self`
        '''
        def operate(self, other):
            '''
            type and bitmask the result to either `self` or `other` whichever
            is larger
            '''
            typ, bits = self.__max_type_bits(other)
            return typ(oper(self, other) & (1 << bits - 1) - 1)
        return operate

    # bitwise operations
    __lshift__  = __ranged(int.__lshift__)
    __rlshift__ = __ranged(int.__rlshift__)
    __rshift__  = __ranged(int.__rshift__)
    __rrshift__ = __ranged(int.__rrshift__)
    __and__     = __typed(int.__and__)
    __rand__    = __typed(int.__rand__)
    __or__      = __typed(int.__or__)
    __ror__     = __typed(int.__ror__)
    __xor__     = __typed(int.__xor__)
    __rxor__    = __typed(int.__rxor__)
    __invert__  = __unary_typed(int.__invert__)

    # arithmetic operations
    if not lt_py3:
        __ceil__  = __unary_typed(int.__ceil__)
        __floor__ = __unary_typed(int.__floor__)
        __int__   = __unary_typed(int.__int__)
    __abs__       = __unary_typed(int.__abs__)
    __pos__       = __unary_typed(int.__pos__)
    __neg__       = __unary_ranged(int.__neg__)
    __add__       = __ranged(int.__add__)
    __radd__      = __ranged(int.__radd__)
    __sub__       = __ranged(int.__sub__)
    __rsub__      = __ranged(int.__rsub__)
    __mod__       = __ranged(int.__mod__)
    __rmod__      = __ranged(int.__rmod__)
    __mul__       = __ranged(int.__mul__)
    __rmul__      = __ranged(int.__rmul__)
    if lt_py3:
        __div__   = __ranged(int.__div__)
        __rdiv__  = __ranged(int.__rdiv__)
    __floordiv__  = __ranged(int.__floordiv__)
    __rfloordiv__ = __ranged(int.__rfloordiv__)
    __pow__       = __ranged(int.__pow__)
    __rpow__      = __ranged(int.__rpow__)


class Int4(Int):
    bits = 4

x, y = Int4(10), Int4(9)
print(x + y)
print(x*y)

在名为answer.py的文件中运行此代码将生成

代码语言:javascript
复制
$ python2.7 answer.py 
3
2
$ python3.4 answer.py 
3
2
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23709429

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档