为什么'是'运营商说这些方法不一样吗?

时间:2014-11-21 20:08:40

标签: python class python-3.x object identity

考虑以下代码:

class Person(object):
   def sayHello(self):
       return 'Hello'

print(Person().sayHello is Person().sayHello)

我希望它显示为True。为什么它显示为假?

6 个答案:

答案 0 :(得分:15)

方法绑定到运行时的实例。运行以下代码时:

print(Person().sayHello is Person().sayHello)

你创建两个实例,每次你有不同的内存地址。

>>> Person().sayHello
<bound method Person.sayHello of <__main__.Person object at 0x7fbe90640410>>
>>> Person().sayHello
<bound method Person.sayHello of <__main__.Person object at 0x7fbe90640490>>

注意:我们在Python中拥有的只是运行时;没有单独的编译时间

答案 1 :(得分:5)

它们是同一类的两个不同实例。 sayHello函数是绑定方法

也就是说,如果你有一个类实例:

p = Person()

并在其上查找属性:

p.sayHello

然后Python首先查看实例的实际属性,如果它没有在那里找到属性,它会查看该类。 如果找到该名称的类方法,则将其转换为绑定到此实例的绑定方法。这就是导致对象实例作为第一个参数(self)传递给sayHello的魔力。

所以Person().sayHello is Person().sayHello创建两个实例,根据在类上定义的相同方法创建两个不同的绑定方法,因此is返回False因为它们是不同的方法。

答案 2 :(得分:4)

我将假设你故意比较方法对象本身 - 而而不是你真的想要比较输出字符串而忘记在{{1}之后放置() }}

尝试此实验:

sayHello

您会看到a = Person() b = Person() a.sayHello b.sayHello 显示为

a.sayHello

...而<bound method Person.sayHello of <__main__.Person instance at 0x102cc8ef0>> 显示相似,但具有不同的父实例指针:

b.sayHello

<bound method Person.sayHello of <__main__.Person instance at 0x102d31908>> 的一个实例的绑定方法本身是来自不同Person实例的同名绑定方法的不同的实例(方法) 。您可以使用Personid(a.sayHello)来确认这一点,它会返回两个相应绑定方法的标识哈希值 - 它们会有所不同。由于您的代码id(b.sayHello) 动态创建了两个Person().sayHello is Person().sayHello个实例,因此情况与我的命名实例示例Persona相同

答案 3 :(得分:-1)

如果您拨打True

,则为sayHello
print(Person().sayHello() is Person().sayHello())

在您的代码中,您实际上是在比较对象上的方法并检查它们是否具有相同的身份(他们不会这样做)。另请注意:

之间的区别
"Hello" is "Hello"

"Hello" == "Hello"

首先,你要比较对象的身份(由于重复使用的字符串是相同的,多次调用id("Hello")来查看)。在第二个中,您将比较字符串的内容以查看它们是否相等(即具有相同的字符)。现在,相同的字符串也具有相同的标识,但我不确定该假设是否适用于所有Python实现。

答案 4 :(得分:-1)

如果你想要一个返回True的表达式,你可以试试这个:

print(Person.sayHello is Person.sayHello) 

只是为了增加混乱,执行:

>>> say = Person.sayHello
>>> say()
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    say()
TypeError: sayHello() missing 1 required positional argument: 'self'

甚至:

>>> say(say)
'Hello'
>>> say(None)
'Hello'
>>> 

这是因为:

>>> say
<function Person.sayHello at 0x02AF04B0>

say是指Person.sayHello这是一个函数,可以调用,但需要一个参数,但在这种特殊情况下,参数是无关紧要的。

现在,如果您不想继续提供无用的参数,您可以自动绑定一个参数:

>>> p=Person()
>>> p.sayHello()
'Hello'

答案 5 :(得分:-2)

运算符意味着两个变量都指向同一个对象,而不是具有相同的值。请参阅Stack Overflow问题 Understanding Python's “is” operator