Python 如何向子类数字类型添加构造函数?

Python 如何向子类数字类型添加构造函数?,python,Python,我想在python中对数值类型(比如int)进行子类化,并为其提供一个闪亮的复杂构造函数。大概是这样的: class NamedInteger(int): def __init__(self, value): super(NamedInteger, self).__init__(value) self.name = 'pony' def __str__(self): return self.name x = NamedInteg

我想在python中对数值类型(比如int)进行子类化,并为其提供一个闪亮的复杂构造函数。大概是这样的:

class NamedInteger(int):
    def __init__(self, value):
        super(NamedInteger, self).__init__(value)
        self.name = 'pony'

    def __str__(self):
        return self.name

x = NamedInteger(5)
print x + 3
print str(x)
class NamedInteger(int):
    def __init__(self, value):
        self.name = 'pony'

    def __str__(self):
        return self.name

x = NamedInteger(5)
print x + 3
print str(x)
x = NamedInteger(5, 'kitty')
class NamedInteger(int):
    def __new__(cls, value, name='pony'):
        self = super(NamedInteger, cls).__new__(cls, value)
        self.name = name
        return self

    def __str__(self):
        return self.name

x = NamedInteger(5)
y = NamedInteger(3, 'kitty')
print "%d %d" % (x, y)
print "%s %s" % (x, y)
这在Python2.4下运行良好,但Python2.6给出了一个弃用警告。在较新的Python版本中,对数值类型进行子类化并为内置类型重新定义构造函数的最佳方法是什么

编辑: 在评论中发现,这在没有super()行的情况下工作,因此可能是这样的:

class NamedInteger(int):
    def __init__(self, value):
        super(NamedInteger, self).__init__(value)
        self.name = 'pony'

    def __str__(self):
        return self.name

x = NamedInteger(5)
print x + 3
print str(x)
class NamedInteger(int):
    def __init__(self, value):
        self.name = 'pony'

    def __str__(self):
        return self.name

x = NamedInteger(5)
print x + 3
print str(x)
x = NamedInteger(5, 'kitty')
class NamedInteger(int):
    def __new__(cls, value, name='pony'):
        self = super(NamedInteger, cls).__new__(cls, value)
        self.name = name
        return self

    def __str__(self):
        return self.name

x = NamedInteger(5)
y = NamedInteger(3, 'kitty')
print "%d %d" % (x, y)
print "%s %s" % (x, y)
我相信这是可行的,因为int是不可变的类型,并且只有
\uuuuu新的\uuuu
方法。但是,我很高兴知道子类化的正确方法,因此我可以构建一个具有如下行为的类:

class NamedInteger(int):
    def __init__(self, value):
        super(NamedInteger, self).__init__(value)
        self.name = 'pony'

    def __str__(self):
        return self.name

x = NamedInteger(5)
print x + 3
print str(x)
class NamedInteger(int):
    def __init__(self, value):
        self.name = 'pony'

    def __str__(self):
        return self.name

x = NamedInteger(5)
print x + 3
print str(x)
x = NamedInteger(5, 'kitty')
class NamedInteger(int):
    def __new__(cls, value, name='pony'):
        self = super(NamedInteger, cls).__new__(cls, value)
        self.name = name
        return self

    def __str__(self):
        return self.name

x = NamedInteger(5)
y = NamedInteger(3, 'kitty')
print "%d %d" % (x, y)
print "%s %s" % (x, y)
第二次编辑:

最终版本现在如下所示:

class NamedInteger(int):
    def __init__(self, value):
        super(NamedInteger, self).__init__(value)
        self.name = 'pony'

    def __str__(self):
        return self.name

x = NamedInteger(5)
print x + 3
print str(x)
class NamedInteger(int):
    def __init__(self, value):
        self.name = 'pony'

    def __str__(self):
        return self.name

x = NamedInteger(5)
print x + 3
print str(x)
x = NamedInteger(5, 'kitty')
class NamedInteger(int):
    def __new__(cls, value, name='pony'):
        self = super(NamedInteger, cls).__new__(cls, value)
        self.name = name
        return self

    def __str__(self):
        return self.name

x = NamedInteger(5)
y = NamedInteger(3, 'kitty')
print "%d %d" % (x, y)
print "%s %s" % (x, y)

下面的答案还提供了到和模块的非常有趣的链接。

如果您不将值传递给
super(NamedInteger,self)。\uuu init\uuu()


我想知道为什么,我从你的帖子中学到:-)

从Python 2.6开始,扩展数值类型的首选方法不是直接从它们继承,而是将类注册为数字抽象基类的子类。查看抽象基类概念的文档

该模块的文档链接到,其中包含可以选择声明自己为其一部分的抽象基类。所以基本上你会说

import numbers
numbers.Number.register(NamedInteger)
表示您的类是数字的一种类型

当然,这样做的问题是,它需要您实现所有不同的处理程序方法,例如
\uuuuuu add\uuuuu
\uuuuu mul\uuuuu
,等等。但是,无论如何,您都必须这样做,因为您不能依赖这些操作的
int
类实现来为您的类做正确的事情。例如,当您将一个整数添加到一个命名整数时,应该发生什么


我的理解是ABC方法旨在迫使你面对这些问题。在这种情况下,最简单的方法可能是将int作为类的实例变量;换句话说,虽然您将注册您的类,使其与
Number
具有
is-a
关系,但您的实现使其与
int
具有
has-a
关系,当您对不可变内置类型进行子类化时,您必须使用
\uuuuu new\uuuu
而不是
\uu init\uuu
,例如:

class NamedInteger(int):

    def __new__(cls, value, name='pony'):
        inst = super(NamedInteger, cls).__new__(cls, value)
        inst.name = name
        return inst

    def __str__(self):
        return self.name

x = NamedInteger(5)
print x + 3                 # => 8   
print str(x)                # => pony
x = NamedInteger(3, "foo")  
print x + 3                 # => 6
print str(x)                # => foo

我将您的代码示例放在反引号中,以便它正确显示。另外,这种方法的问题是,
NamedInteger
没有用正确的值初始化。啊,你是对的,你有一双敏锐的眼睛来发现它!我想现在我有了一个想法,为什么没有super()+1这个好问题,这个变化的历史请看。