如何创建一个独特的对象?(这是一个关于IT技术的提问标题)

5

I want

class MyClass(object):
    _my_unique = ????      # if this were lisp, I would have written (cons nil nil) here

    def myFunc (self, arg):
        assert arg != _my_unique    # this must never fail
        ...

如何替代???以确保assert永远不会失败?

(在Lisp中,我可以使用(cons nil nil)创建_my_unique并在assert中使用eq。)

PS. 应用场景:我将在dict中放置_my_unique,因此我希望它等于自身,但我不希望它与外部传入的任何内容相等(在dict碰撞意义上)。


你想设置对象的属性吗? - tjati
我认为你必须有一些额外的条件没有说明,否则任何永远不等于自身的东西,比如float(nan),都可以满足要求。 - DSM
我对使用场景感到困惑。你为什么要包含一个永远不会失败的assert呢?那不是一行毫无意义的代码吗?只需删除“assert”,它就不会失败,我保证! :) - Adam Smith
@AdamSmith:大多数人只会在“不应该失败”的情况下添加断言。毕竟,如果你预计它会失败,那么你可以编写代码来处理这个失败。断言将在依赖于该值的代码运行之前让你知道它是否失败。 - Bryan Oakley
@BryanOakley 对的,但问题的措辞让人觉得他想要一个永远不会失败的选项,因为宇宙的法则保证了它,就像 assert 1 < 2。如果那个断言失败了,你说得对,我希望尽早知道! :) - Adam Smith
4个回答

6
你可以使用object(),但这并不能保证断言“永远不会失败”。如果你调用myFunc并将MyClass.my_unique作为对象传递,它仍然会失败。此外,如果你想测试是否是同一个对象,请使用arg is not my_unique而不是!=

我该如何确保外部世界无法看到 MyClass.my_unique - sds
我的assert测试必须与dict使用的测试相同,参见PS - sds
2
@sds 你不能这样做。你可以在前面加下划线,礼貌地要求不要这样做,但你不能将任何内容设为私有。 - joojaa
@sds 这是Python哲学:它适用于Python的特点,即不是一个经过安全验证的语言。这完全没问题。 - Mayou36

2

您可以使用object()

object返回一个新的无特征对象。它是所有新式类的基类,并具有所有新式类实例共同的方法。


0

如果你问的是“如何使每个MyClass实例中的_my_unique都是唯一的”,你可以在构造函数中创建一个新的空对象。

例如:

>>> class MyClass(object):
...     def __init__(self):
...         self._my_unique = object()
... 
>>> foo=MyClass()
>>> bar=MyClass()
>>> foo._my_unique
<object object at 0x100ce70c0>
>>> bar._my_unique
<object object at 0x100ce7090>

如果你想隐藏_my_unique,给它加上两个下划线。这样,没有人可以意外地获取到该值。虽然不是完全不可能,但他们需要更加努力才能获取到该值。这被称为名称修饰,你可以在这里阅读更多相关信息:http://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references
>>> class MyClass(object):
...     def __init__(self):
...         self.__my_unique = object()
... 
>>> foo=MyClass()
>>> foo.__my_unique
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute '__my_unique'

-2

这是一个有点混淆的问题,因为它似乎混合了一堆没有目的的概念。首先,在 Python 中,大多数任何对象都是唯一的,但可能有多种方法可以到达它们。检查身份的运算符不是 !=(不等于),而是 is not。与 Java 不同,Python 不要求您将事物放在类中,并且不会隐式地查找 self(他们知道它作为隐式的 this)。Lisp 中的 cons 用于构造成对出现的元素,这些元素通常形成单链表,这是一种在 Python 中不常见的结构,因为我们使用动态引用数组称为列表。列表是可变的,因此使用 list()[] 构造一个列表将产生一个唯一的对象。

因此,虽然这是相当无意义的,但编写一个生成执行无用断言的函数的函数的一种方法可能是:

def createfunc():
  mylist=[]
  def subfunc(x):
    assert x is not mylist
  return subfunc

每次调用createfunc()都会返回一个具有自己的mylist的新函数。然而,该对象的唯一性并不意味着无法访问它:
f=createfunc()
f(f.func_closure[0].cell_contents)   # raises AssertionError

关于PS,为了与字典碰撞相关,请确保您的对象也是可哈希的,这使得object()list()更适合作为唯一对象的选择。

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