1
Python 2.7.3 (default, Aug  1 2012, 05:14:39) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Image
>>> im = Image.open("test.jpeg")
>>> data = im.load()
>>> data.__setitem__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'PixelAccess' object has no attribute '__setitem__'
>>> help(data)

>>> data.__setitem__
<method-wrapper '__setitem__' of PixelAccess object at 0x7f4d9ae4b170>

这是我见过的最奇怪的事情。

我正在用图书馆 PIL 做一个项目。' data' 是 的对象PixelAccess。它具有__setitem__in的属性help(data)

你可以做' data[x,y] = value'来分配坐标中的像素值(x,y)

Help on PixelAccess object:

class PixelAccess(object)
 |  Methods defined here:
 |  
 |  __delitem__(...)
 |      x.__delitem__(y) <==> del x[y]
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __setitem__(...)
 |      x.__setitem__(i, y) <==> x[i]=y

为什么在函数之前不__setitem__存在而在help()函数之后出现?

即使在我执行快递' data[x,y] = value'之后也是一样的。它只在help()函数之后出现。

怎么解释?

4

1 回答 1

1

确实 - 这是一些奇怪的行为。但问题不是 __getitem__不存在 - 它存在,只是由于 PIL 代码中的一些问题而暂时隐藏 - 可能是由于允许延迟加载图像的机制导致的错误。

这不应该给您带来麻烦 - 您的情况下的“数据”是 PIL 的“PixelAccess”对象,它允许您使用元组作为索引来访问图像像素。在对其执行“dir”时,它确实显示“empty”,如果您尝试获取它的__getitem__方法,则会引发属性错误,确实:

>>> from PIL import Image
>>> img = Image.open("images/rock.png")
>>> d1 = img.load()
>>> dir (d1)
[]
>>> d1.__getitem__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'PixelAccess' object has no attribute '__getitem__'
>>> # However, this works:
... 
>>> d1[32,32]
(255, 255, 255, 255)
>>> d1.__getitem__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'PixelAccess' object has no attribute '__getitem__'
>>> 

正如我所说,这很可能是 PIL 用于创建 PixelAcces 对象的任何机制的副作用。如果你真的需要访问你的PixelAccess.__getitem__方法,获得它的方法是绕过 Python 中的大多数属性隐藏技巧:你确实使用object__getattribute__方法来检索它。

(一旦以这种方式完成,令人惊讶的是,PixelAccess 对象在 dir 中不再显示为空):

>>> dir(d1)
[]
>>> getattr(d1, "__getitem__")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'PixelAccess' object has no attribute '__getitem__'
>>> object.__getattribute__(d1, "__getitem__")
<method-wrapper '__getitem__' of PixelAccess object at 0x7f94e6f37170>
>>> # there is our man
... 
>>> getattr(d1, "__getitem__")
<method-wrapper '__getitem__' of PixelAccess object at 0x7f94e6f37170>
>>> # and this works now
... 
>>> dir(d1)
['__class__', '__delattr__', '__delitem__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__']
>>> 

总而言之,object.__getattribute__如上所示的调用应该是“确定性的”,以便您获取方法。

至于在此之前它隐藏了哪些机制,以及是什么导致它以及对象的所有其他成员在以这种形式自省后出现,唯一知道的方法是深入研究 PIL 的代码。

于 2012-10-14T08:10:08.627 回答