gpt4 book ai didi

python - 避免使用两个不同的数字子类(int 和 long)?

转载 作者:太空狗 更新时间:2023-10-30 01:02:51 25 4
gpt4 key购买 nike

在本质上处理自定义枚举类型实现时,我遇到了一种情况,似乎我必须从 int 派生出单独但几乎 相同的子类>long 因为它们在 Python 中是不同的类。这似乎有点讽刺,因为两者的实例通常可以互换使用,因为在大多数情况下,它们只是在需要时自动创建。

我的工作正常,但本着 DRY(不要重复自己)的精神,我不禁想知道是否有更好的方法,或者至少是更简洁的方法来完成此任务。目标是让子类实例可以在任何地方使用——或者尽可能接近——它们的基类实例本来可以使用的地方。理想情况下,这应该自动发生,类似于内置 int() 在检测到需要时实际返回 long 的方式。

这是我当前的实现:

class NamedInt(int):
"""Subclass of type int with a name attribute"""
__slots__ = "_name" # also prevents additional attributes from being added

def __setattr__(self, name, value):
if hasattr(self, name):
raise AttributeError(
"'NamedInt' object attribute %r is read-only" % name)
else:
raise AttributeError(
"Cannot add attribute %r to 'NamedInt' object" % name)

def __new__(cls, name, value):
self = super(NamedInt, NamedInt).__new__(cls, value)
# avoid call to this subclass's __setattr__
super(NamedInt, self).__setattr__('_name', name)
return self

def __str__(self): # override string conversion to be name
return self._name

__repr__ = __str__


class NamedLong(long):
"""Subclass of type long with a name attribute"""
# note: subtypes of variable length 'long' type can't have __slots__

def __setattr__(self, name, value):
if hasattr(self, name):
raise AttributeError(
"NamedLong object attribute %r is read-only" % name)
else:
raise AttributeError(
"Cannot add attribute %r to 'NamedLong' object" % name)

def __new__(cls, name, value):
self = super(NamedLong, NamedLong).__new__(cls, value)
# avoid call to subclass's __setattr__
super(NamedLong, self).__setattr__('_name', name)
return self

def __str__(self):
return self._name # override string conversion to be name

__repr__ = __str__

class NamedWholeNumber(object):
"""Factory class which creates either a NamedInt or NamedLong
instance depending on magnitude of its numeric value.
Basically does the same thing as the built-in int() function
does but also assigns a '_name' attribute to the numeric value"""
class __metaclass__(type):
"""NamedWholeNumber metaclass to allocate and initialize the
appropriate immutable numeric type."""
def __call__(cls, name, value, base=None):
"""Construct appropriate Named* subclass."""
# note the int() call may return a long (it will also convert
# values given in a string along with optional base argument)
number = int(value) if base is None else int(value, base)

# determine the type of named numeric subclass to use
if -sys.maxint-1 <= number <= sys.maxint:
named_number_class = NamedInt
else:
named_number_class = NamedLong

# return instance of proper named number class
return named_number_class(name, number)

最佳答案

下面是如何通过多重继承解决 DRY 问题。不幸的是,它不能很好地与 __slots__ 一起使用(它会导致编译时 TypeError)所以我不得不将其排除在外。希望 __dict__ 值不会为您的用例浪费太多内存。

class Named(object):
"""Named object mix-in. Not useable directly."""
def __setattr__(self, name, value):
if hasattr(self, name):
raise AttributeError(
"%r object attribute %r is read-only" %
(self.__class__.__name__, name))
else:
raise AttributeError(
"Cannot add attribute %r to %r object" %
(name, self.__class__.__name__))

def __new__(cls, name, *args):
self = super(Named, cls).__new__(cls, *args)
super(Named, self).__setattr__('_name', name)
return self

def __str__(self): # override string conversion to be name
return self._name

__repr__ = __str__

class NamedInt(Named, int):
"""NamedInt class. Constructor will return a NamedLong if value is big."""
def __new__(cls, name, *args):
value = int(*args) # will raise an exception on invalid arguments
if isinstance(value, int):
return super(NamedInt, cls).__new__(cls, name, value)
elif isinstance(value, long):
return NamedLong(name, value)

class NamedLong(Named, long):
"""Nothing to see here."""
pass

关于python - 避免使用两个不同的数字子类(int 和 long)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12978393/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com