每个Python对象都有一个整数。

3

可能是重复问题:
为类实例自动递增 ID

我想在 Python 中实现像以下 Java 类的功能:

public class MyObject {
    private static int ID = 0;
    private final int id;
    public MyObject() {
        id = ID++;
    }
}

在这段Java代码中,每个myObject都将有一个id,并且不可能存在两个对象具有相同的ID(它是一个单线程应用程序)。

我可以在Python中做类似的事情吗?


在Python中,你真的不应该将变量命名为id,因为这是返回对象标识符的内置函数的名称。 - abarnert
3个回答

8
在Python中,您可以直接引用类属性:
class MyObject(object):
    ID = 0

    def __init__(self):
       self.id = MyObject.ID = MyObject.ID + 1

示例:

>>> class MyObject(object):
...     ID = 0
...     def __init__(self):
...        self.id = MyObject.ID = MyObject.ID + 1
... 
>>> MyObject().id
1
>>> MyObject().id
2
>>> MyObject().id
3
>>> MyObject.ID
3

为什么每次访问id时它都会改变?上面的代码并没有这样做。 - Whymarrh
1
他只是说每个对象需要一个uid,而不是它们必须是连续的。对他来说,id()也可能同样有效(除非GC的对象的ID可能会被重新应用于新对象,这是一个问题)。 - Silas Ray
@Whymarrh,这是因为每个“id”都来自不同的对象。每个新对象都被分配一个唯一的ID号码。 - Mark Ransom
这很有道理,我把创建一个新对象和访问一个对象搞混了。 - Whymarrh
1
请注意,Java代码在递增之前分配ID,而此代码在递增之后分配。 - Mark Ransom
不必手动管理计数器,你可以在类中使用 idcounter = itertools.count(),然后使用 self.id = next(MyObject.idcounter)。这样也会从0开始(就像Java代码一样)。 - abarnert

2
如我在@Martjin Pieters'的答案评论中提到的,内置函数id()可能已经足够满足您的需求。 id(obj)返回系统中任何对象的唯一ID(实际上,在某些解释器中是内存地址)。 除非您的对象频繁被销毁但是您的ID引用需要在销毁后保持有效,否则id()应该可以满足您的唯一ID需求。
从文档中得知:

[id()返回的值]是一个整数(或长整数),在其生命周期内保证为此对象唯一且恒定。 生命周期不重叠的两个对象可能具有相同的id()值。


1
+1。但是引用文档(“这是一个整数(或长整数),在其生命周期内保证对于此对象是唯一且恒定的。生命周期不重叠的两个对象可能具有相同的id()值。”)或类似的help(id)文本可能是值得的。 - abarnert

1

@Martjin Pieters 的想法是正确的,但我建议使用 itertools.count

class MyObject(object):
    ID = itertools.count()

    def __init__(self):
       self.id = MyObject.ID.next()

>>> MyObject().id
0
>>> MyObject().id
1
>>> MyObject().id
2
>>> MyObject.ID
count(3)

希望这能有所帮助。

制作整个迭代器对象只为增加一个整数有什么好处?这种用例似乎并不复杂,无法证明其正当性。 - Silas Ray
如果您意外按下 = 而不是 +,会发生什么?如果在意识到要递增 n!=1 之前,您在多个方法中进行了递增,又会发生什么... - inspectorG4dget
“如果您打错了字”同样适用于任何解决方案。至于其他的假设,OP明确说明了他的要求。为了支持每个假设的使用情况而过度设计并不具有价值。设计解决您所面临的问题和可以预测到的增长,而不是“如果这被用来存储核密码”的场景。除非您认为您应该在家庭厨房中拥有其中之一:http://www.foodprocessing-technology.com/contractors/industrial_ovens/sveba/sveba5.html - Silas Ray
我并不是在支持“每一个可能的用例”。我只是做了一个小改变,如果需要的话,可以支持许多其他用例。无论哪种情况,c.next()MyClass._ID += 1更简洁。这不像是我试图让它为我做早餐作为其功能的扩展 - 更像是我让它对其预期功能更加灵活。 - inspectorG4dget
任何会编程的人都能理解 MyClass._ID += 1MyClass._ID = c.next() 更加晦涩,不够简洁。 - Silas Ray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接