不同的实例是否共享在类中声明的相同方法?

时间:2018-05-28 17:37:36

标签: python python-3.x

我想知道Python 3(不是2,请:P)如何解决以下情况:

我有一个班级和两个实例:

class MyClass:
   def something():
      pass

a = MyClass()
b = MyClass()

a.somethingb.something是否共享相同的内存地址,或者每个人都声明了something?调用a.something的解决方案如何运作?

当我尝试查看方法id时,它们具有相同的内容:

id(a.something), id(b.something) # (4487791304, 4487791304)

但是当我用is来比较它是否相同时,结果是'False:

id(a.something) is id(b.something) # 

如果我更进一步,打印ab的可用方法和数据属性,我可以看到它们都声明了something

['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'something']

谢谢。

3 个答案:

答案 0 :(得分:1)

  

Y-M-Da.something是否共享相同的内存地址,或者每个人都声明了b.something

既不! \ O /

表达式something每次评估为a.something的新绑定版本。这意味着MyClass.something甚至不需要进入它:

b

>>> a.something is a.something False s相同的原因与方法无关:

id

第一个对象被创建>>> id(object()) == id(object()) True # on CPython d,并在第二个对象被丢弃之前被丢弃,因此id被回收。

答案 1 :(得分:0)

此:

id(a.something) is id(b.something)

是假的,原因有两个:

  • is相比,相同(非小)整数不相同。这里的简短故事几乎从不使用is
  • 但即使a == b这是False

>>> id(a.something) is id(a.something)
False

这是因为函数是描述符对象;每次执行a.something时,每次都会创建一个新的绑定方法。

回到原来的问题:

ab的(未绑定)方法是相同的,内存位置也是如此,您可以看到id(a.something) == id(b.something)

答案 2 :(得分:0)

  

不同的实例是否共享在类中声明的相同方法?

是和否。

如果您访问不同字节编译代码中的属性,您将始终获得不同的对象:

In [12]: id(a.something)
Out[12]: 140252085300232

In [13]: id(b.something)
Out[13]: 140252110215816

这是完全可以理解的,因为当您创建不同的对象时,默认的期望应该是这些对象即使它们是来自同一对象的实例也不应该影响彼此的功能。这就是说,如果他们共享相同的方法,其中一个更改适用于该方法,另一个也将受到影响,这是完全错误的!

但是否则你会得到相同的id。当您执行以下操作时,您获得相同id的原因是:

id(a.something), id(b.something) 

是因为当您尝试从字节编译在一起的代码中的不同实例访问相同的属性时,Python(CPython实现)不会重新创建该方法(至少就您没有更改方法而言)。这实际上是一个内部优化,它可以防止Python解释器在您没有通过调用__set__描述符来更改方法时创建多个对象。

你也可以用一个函数来测试它(不仅仅是在一个元组中),它的体内代码是字节编译在一起的:

In [8]: def foo():
   ...:     print(id(a.something))
   ...:     print(id(b.something))
   ...:     

In [9]: 

In [9]: foo()
140252085766536
140252085766536

同样如评论中所述,您不应使用is运算符来检查整数的相等性,只需使用==即可。原因是小于-5且大于256的整数不会缓存在内存中(就像那个范围内的那些整数)。这意味着具有相同值的数字在内存中具有不同的id。您可以查看以下内容:

In [14]: 256 is 255+1
Out[14]: True

In [15]: 257 is 255+2
Out[15]: False