“索引属性”...... [英] "indexed properties"...

查看:46
本文介绍了“索引属性”......的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很难用一个问题来表达这个问题

...


前几天我看到有人要求的帖子/>
关于可覆盖的属性,没有人提供

属性为坏的建议。所以也许我们已经克服了b $ b。我认为属性可以有

如果用户不知道它们存在会产生不良后果

并且认为对象的某个属性是

只是一个普通的属性。但这几乎适用于任何语言的任何方面。


如果一个人来自,例如,Object Pascal(Delphi)

然后属性很难没有。那天

我决定我想要什么OP称为

" indexed property"或数组属性。无法获得
弄清楚如何使_property_表现得那样。

所以我读了一些关于描述符的内容,并且

几分钟后我有一个索引属性的东西

就像属性一样,除了它给

一个索引属性!这太酷了。


为什么?例如,Matrix应该有一行[n]

属性,允许像


m.row [0] = m.row [1] + m.row [2]


好​​的,你可以通过将行

作为一个普通的Row对象列表来做_that_。但是那么

你不得不说


m.row [0] =排([1,2,3])


我希望能说的话


m.row [0] = [1,2,3]


并自动创建Row。


_Also_这些索引属性我的矩阵

可以有m.row [j]和m.col [k]看起来与客户端完全相同 - 我们不想在内部存储

行列表并存储相同的
列中的
数据。太酷了。


嗯,这里没有一个有效的借口。

嗯,对,我们走了:任何人看到问题或者

实现可能的改进

下面的indexedproperty?


""" indexed.py:" indexedproperty" ;或多或少的工作

喜欢property除了它给出Object Pascal中的内容

将是一个索引属性。参见

__name __ =" __ main __"以下部分为演示


"""


class WriteOnlyIP(例外):

def __str __(自我):

返回"""


索引属性是只写的


"""


class ReadOnlyIP(例外):

def __str __(自我):

返回"" ;"


索引属性是只读的


"""


class indexedproperty(object):

def __init __(self,getitem = None,setitem = None):

self.getitem = getitem

self.setitem = setitem


def __get __(self,obj,owner):

self.obj = obj

返回自我


def __getitem __(自我,索引):

如果self.getitem:

返回self.getitem(self.obj,索引)

否则:

加注WriteOnlyIP


def __setitem __(自我,索引,价值):

如果self.setitem:

self.setitem(self.obj,index,value)

else:

raise ReadOnlyIP

if __name__ ==" __ main __":


类AClass(对象):

def __init __(自我):

self.cells = [[0,0], [0,0]]


def SetCell(自我,(行,col),值):

self.cells [row] [col] =价值


def GetCell(自我,(行,col)):

返回self.cells [row] [col]


cell = indexedproperty(GetCell,SetCell)


C = AClass()

行范围(2):

for col in range(2):

C.cell [row,col] =" row:%s,col:%s" %(row,col)


表示范围内的行(2):

表示范围内的col(2):

print C.cell [row,col]

C.cell [0,0],C.cell [1,1] = C.cell [1,1],C。单元格[0,0]


print" C.cell [0,0],C.cell [1,1] = C.cell [1,1],C .cell [0,0]:


范围内的行(2):

for col in range(2):

打印C.cell [row,col]


-

David C. Ullrich

Having a hard time phrasing this in the form
of a question...

The other day I saw a thread where someone asked
about overrideable properties and nobody offered
the advice that properties are Bad. So maybe we''ve
got over that. I suppose properties could have
Bad consequences if a user doesn''t know they exist
and think that a certain property of an object is
just an ordinary attribute. But that applies to
almost any aspect of any language.

If a person comes from, say, Object Pascal (Delphi)
then properties are hard to live without. The
other day I decided I wanted what OP calls an
"indexed property" or "array property". Couldn''t
figure out how to make a _property_ behave that way.
So I read a little bit about descriptors, and a
few minutes later I had an indexedproperty thing
that works just like property, except it gives
an indexed property! This is just too cool.

Why? For example, a Matrix should have a row[n]
property allowing things like

m.row[0] = m.row[1] + m.row[2]

Ok, you could do _that_ by just making row
an ordinary list of Row objects. But then
you''d have to say

m.row[0] = Row([1,2,3])

where I want to be able to say

m.row[0] = [1,2,3]

and have the Row created automatically.

_Also_ with these indexed properties my Matrix
can have m.row[j] and m.col[k] that look exactly
the same to a client - we don''t want to store a
list of rows internally and also store the same
data in a list of columns. Too cool.

Hmm, none of that''s a valid excuse for a post here.
Um, right, here we go: Anyone see problems or
possible improvements with the implementation
of indexedproperty below?

"""indexed.py: "indexedproperty" works more or less
like "property" except it gives what in Object Pascal
would be an "indexed property". See the
__name__="__main__" section below for a demo

"""

class WriteOnlyIP(Exception):
def __str__(self):
return """

indexed property is write-only

"""

class ReadOnlyIP(Exception):
def __str__(self):
return """

indexed property is read-only

"""

class indexedproperty(object):
def __init__(self, getitem=None, setitem=None):
self.getitem = getitem
self.setitem = setitem

def __get__(self, obj, owner):
self.obj = obj
return self

def __getitem__(self, index):
if self.getitem:
return self.getitem(self.obj, index)
else:
raise WriteOnlyIP

def __setitem__(self, index, value):
if self.setitem:
self.setitem(self.obj, index, value)
else:
raise ReadOnlyIP
if __name__ == "__main__":

class AClass(object):
def __init__(self):
self.cells = [[0,0], [0,0]]

def SetCell(self, (row, col), value):
self.cells[row][col] = value

def GetCell(self, (row, col)):
return self.cells[row][col]

cell = indexedproperty(GetCell, SetCell)

C = AClass()
for row in range(2):
for col in range(2):
C.cell[row, col] = "row: %s, col: %s" % (row, col)

for row in range(2):
for col in range(2):
print C.cell[row, col]

C.cell[0,0], C.cell[1,1] = C.cell[1,1], C.cell[0,0]

print "After C.cell[0,0], C.cell[1,1] = C.cell[1,1], C.cell[0,0]:"

for row in range(2):
for col in range(2):
print C.cell[row, col]

--
David C. Ullrich

推荐答案

En Wed,2008年5月14日18:15:41 -0300,David C. Ullrich

< du ****** @sprynet.comescribió:
En Wed, 14 May 2008 18:15:41 -0300, David C. Ullrich
<du******@sprynet.comescribió:

很难用一个问题来表达这个问题

一个问题...


前几天,我看到一个帖子,有人询问

有关可覆盖的属性,没有人提供

属性为坏的建议。所以也许我们已经克服了b $ b。我认为属性可以有

如果用户不知道它们存在会产生不良后果

并且认为对象的某个属性是

只是一个普通的属性。但这几乎适用于任何语言的任何方面。


如果一个人来自,例如,Object Pascal(Delphi)

然后属性很难没有。那天

我决定我想要什么OP称为

" indexed property"或数组属性。无法获得
弄清楚如何使_property_表现得那样。

所以我读了一些关于描述符的内容,并且

几分钟后我有一个索引属性的东西

就像属性一样,除了它给

一个索引属性!这太酷了。


为什么?例如,Matrix应该有一行[n]

属性,允许像


m.row [0] = m.row [1] + m.row [2]


好​​的,你可以通过将行

作为一个普通的Row对象列表来做_that_。但是那么

你不得不说


m.row [0] =排([1,2,3])


我希望能说的话


m.row [0] = [1,2,3]


并自动创建Row。


_Also_这些索引属性我的矩阵

可以有m.row [j]和m.col [k]看起来与客户端完全相同 - 我们不想在内部存储

行列表并存储相同的
列中的
数据。太酷了。


嗯,这里没有一个有效的借口。

嗯,对,我们走了:任何人看到问题或者

实现可能的改进

下面的indexedproperty?


""" indexed.py:" indexedproperty" ;或多或少的工作

喜欢property除了它给出Object Pascal中的内容

将是一个索引属性。参见

__name __ =" __ main __"以下部分为演示


"""


class WriteOnlyIP(例外):

def __str __(自我):

返回"""


索引属性是只写的


"""


class ReadOnlyIP(例外):

def __str __(自我):

返回"" ;"


索引属性是只读的


"""


class indexedproperty(object):

def __init __(self,getitem = None,setitem = None):

self.getitem = getitem

self.setitem = setitem


def __get __(self,obj,owner):

self.obj = obj

返回自我


def __getitem __(自我,索引):

如果self.getitem:

返回self.getitem(self.obj,索引)

否则:

提高WriteOnlyIP


def __setitem __(self,index,va lue):

if self.setitem:

self.setitem(self.obj,index,value)

else:

筹集ReadOnlyIP


如果__name__ ==" __ main __":


class AClass(object):

def __init __(自我):

self.cells = [[0,0],[0,0]]


def SetCell(self ,(row,col),value):

self.cells [row] [col] = value


def GetCell(self,(row,col) )):

返回self.cells [row] [col]


cell = indexedproperty(GetCell,SetCell)


C = AClass()

范围内的行(2):

范围内的col(2):

C. cell [row,col] =" row:%s,col:%s" %(row,col)


表示范围内的行(2):

表示范围内的col(2):

print C.cell [row,col]

C.cell [0,0],C.cell [1,1] = C.cell [1,1],C。单元格[0,0]


print" C.cell [0,0],C.cell [1,1] = C.cell [1,1],C .cell [0,0]:


范围内的行(2):

for col in range(2):

打印C.cell [row,col]
Having a hard time phrasing this in the form
of a question...

The other day I saw a thread where someone asked
about overrideable properties and nobody offered
the advice that properties are Bad. So maybe we''ve
got over that. I suppose properties could have
Bad consequences if a user doesn''t know they exist
and think that a certain property of an object is
just an ordinary attribute. But that applies to
almost any aspect of any language.

If a person comes from, say, Object Pascal (Delphi)
then properties are hard to live without. The
other day I decided I wanted what OP calls an
"indexed property" or "array property". Couldn''t
figure out how to make a _property_ behave that way.
So I read a little bit about descriptors, and a
few minutes later I had an indexedproperty thing
that works just like property, except it gives
an indexed property! This is just too cool.

Why? For example, a Matrix should have a row[n]
property allowing things like

m.row[0] = m.row[1] + m.row[2]

Ok, you could do _that_ by just making row
an ordinary list of Row objects. But then
you''d have to say

m.row[0] = Row([1,2,3])

where I want to be able to say

m.row[0] = [1,2,3]

and have the Row created automatically.

_Also_ with these indexed properties my Matrix
can have m.row[j] and m.col[k] that look exactly
the same to a client - we don''t want to store a
list of rows internally and also store the same
data in a list of columns. Too cool.

Hmm, none of that''s a valid excuse for a post here.
Um, right, here we go: Anyone see problems or
possible improvements with the implementation
of indexedproperty below?

"""indexed.py: "indexedproperty" works more or less
like "property" except it gives what in Object Pascal
would be an "indexed property". See the
__name__="__main__" section below for a demo

"""

class WriteOnlyIP(Exception):
def __str__(self):
return """

indexed property is write-only

"""

class ReadOnlyIP(Exception):
def __str__(self):
return """

indexed property is read-only

"""

class indexedproperty(object):
def __init__(self, getitem=None, setitem=None):
self.getitem = getitem
self.setitem = setitem

def __get__(self, obj, owner):
self.obj = obj
return self

def __getitem__(self, index):
if self.getitem:
return self.getitem(self.obj, index)
else:
raise WriteOnlyIP

def __setitem__(self, index, value):
if self.setitem:
self.setitem(self.obj, index, value)
else:
raise ReadOnlyIP
if __name__ == "__main__":

class AClass(object):
def __init__(self):
self.cells = [[0,0], [0,0]]

def SetCell(self, (row, col), value):
self.cells[row][col] = value

def GetCell(self, (row, col)):
return self.cells[row][col]

cell = indexedproperty(GetCell, SetCell)

C = AClass()
for row in range(2):
for col in range(2):
C.cell[row, col] = "row: %s, col: %s" % (row, col)

for row in range(2):
for col in range(2):
print C.cell[row, col]

C.cell[0,0], C.cell[1,1] = C.cell[1,1], C.cell[0,0]

print "After C.cell[0,0], C.cell[1,1] = C.cell[1,1], C.cell[0,0]:"

for row in range(2):
for col in range(2):
print C.cell[row, col]




-

Gabriel Genellina



--
Gabriel Genellina


En Wed,2008年5月14日18:15:41 -0300,David C. Ullrich< du ****** @sprynet.comescribió:
En Wed, 14 May 2008 18:15:41 -0300, David C. Ullrich <du******@sprynet.comescribió:

很难用一个问题来表达这个问题

一个问题...


前几天我看到一个帖子,有人询问

关于可覆盖的属性,没有人提供

属性为坏的建议。所以也许我们已经克服了b $ b。我认为属性可以有

如果用户不知道它们存在会产生不良后果

并且认为对象的某个属性是

只是一个普通的属性。但这几乎适用于任何语言的任何方面。


Having a hard time phrasing this in the form
of a question...

The other day I saw a thread where someone asked
about overrideable properties and nobody offered
the advice that properties are Bad. So maybe we''ve
got over that. I suppose properties could have
Bad consequences if a user doesn''t know they exist
and think that a certain property of an object is
just an ordinary attribute. But that applies to
almost any aspect of any language.



哪种不良后果你在想什么?除了用户没有意识到某些操作的复杂性,或者getter / setter非常耗时(在这种情况下我会使用公共的getXXX / setXXX函数来强调某事正在发生,而不是只是一个属性查找)

Which "bad consequences" are you thinking of? Apart from the user not being aware of the complexity of certain operations, or a getter/setter very time-consuming (in that case I''d use public getXXX/setXXX functions instead, to emphasize that "something" is happening, not just an attribute lookup)


如果一个人来自,例如,对象Pascal(德尔福)

那么属性很难没有。
If a person comes from, say, Object Pascal (Delphi)
then properties are hard to live without. The



您应该阅读文章Python is not Java。如果你还没有这样做的话。
http://dirtsimple.org/2004/12/python-is-not-java.html


其他一天我觉得我想要什么OP称之为

索引属性或数组属性。无法获得
弄清楚如何使_property_表现得那样。

所以我读了一些关于描述符的内容,并且

几分钟后我有一个索引属性的东西

就像属性一样,除了它给

一个索引属性!这太酷了。


为什么?例如,Matrix应该有一行[n]

属性,允许像


m.row [0] = m.row [1] + m.row [2]


好​​的,你可以通过将行

作为一个普通的Row对象列表来做_that_。但是那么

你不得不说


m.row [0] =排([1,2,3])


我希望能说的话


m.row [0] = [1,2,3]


并自动创建Row。
other day I decided I wanted what OP calls an
"indexed property" or "array property". Couldn''t
figure out how to make a _property_ behave that way.
So I read a little bit about descriptors, and a
few minutes later I had an indexedproperty thing
that works just like property, except it gives
an indexed property! This is just too cool.

Why? For example, a Matrix should have a row[n]
property allowing things like

m.row[0] = m.row[1] + m.row[2]

Ok, you could do _that_ by just making row
an ordinary list of Row objects. But then
you''d have to say

m.row[0] = Row([1,2,3])

where I want to be able to say

m.row[0] = [1,2,3]

and have the Row created automatically.



在这种情况下,可以使* row *成为具有自定义__getitem __ / __ setitem__的对象。但我更喜欢在我的物体上尽可能少的魔法:如果它说m.row [0] = [1,2,3]我希望m.row [0]实际上*是*那个列表(只要有可能) ,而不是从[1,2,3]参数初始化的任何其他对象。 (也许这是对C ++魔法构造函数和如此可怕的事情的一些过度反应......)

One could make *row* an object with a custom __getitem__/__setitem__ in this case. But I prefer to have as little magic as possible on my objects: if it says m.row[0] = [1,2,3] I expect m.row[0] to actually *be* that list (whenever possible), and not any other object initialized from the [1,2,3] arguments. (Maybe this is some overreaction against C++ "magic" constructors and such horrible things...)


_Also_这些索引属性我的矩阵

可以让m.row [j]和m.col [k]看起来与客户完全相同

- 我们不想存储

内部的行列表,并将相同的

数据存储在列列表中。太酷了。
_Also_ with these indexed properties my Matrix
can have m.row[j] and m.col[k] that look exactly
the same to a client - we don''t want to store a
list of rows internally and also store the same
data in a list of columns. Too cool.



如上所述,m.row和m.col是自定义对象同样可以实现。

The same can be achieved having m.row and m.col be custom objects like I said above.


嗯,这里没有一个有效的借口。

嗯,对,我们走了:任何人看到问题或

可能的改进实施

下面的indexedproperty?
Hmm, none of that''s a valid excuse for a post here.
Um, right, here we go: Anyone see problems or
possible improvements with the implementation
of indexedproperty below?



请注意,属性对象(或indexedproperty)是* class *属性。也就是说,在所有实例之间共享。

Note that the property object (or your indexedproperty) is a *class* attribute. That is, shared among all instances.


class indexedproperty(object):

def __init __(self,getitem = None,setitem = None ):

self.getitem = getitem

self.setitem = setitem


def __get __(self,obj,owner):

self.obj = obj

返回自我
class indexedproperty(object):
def __init__(self, getitem=None, setitem=None):
self.getitem = getitem
self.setitem = setitem

def __get__(self, obj, owner):
self.obj = obj
return self



这是问题所在。你不能存储obj。在自我中因为它在所有实例之间共享。您的示例不会显示任何问题,因为所有属性访问后立即使用相同的对象进行getitem访问。试试这个:


x = AClass()

y = AClass()

x.cell [0,0] = 1

print x.cell [1,1] #output:0

y.cell [x.cell [0,0],x.cell [0,0]] = 2

打印y.cell [1,1]#应该是2,仍然是0

打印x.cell [1,1]#应该仍为0,但是改变,现在2


解决方法是返回__get__中的另一个对象而不是self,它会记住obj。实例,或者一个闭包,或者......

但是我没有看到这一点,使用.cell的另一个对象要容易得多(它更清楚,没有打破封装,划分责任......)


类Matrix2x2(对象):

def __init __(自我):

self.cells = [[0,0],[0,0]]


def __setitem __(self,(row,col),value):

self.cells [row] [col] = value


def __getitem __(self,(row,col)):

返回self。单元格[row] [col]


class AClass(object):

def __init __(self):

self.cell = Matrix2x2()

-

Gabriel Genellina

Here is the problem. You can''t store "obj" in "self" because it is shared among all instances. Your examples don''t show any problem because all property accesses are immediately followed by a getitem access using the same object. Try this:

x = AClass()
y = AClass()
x.cell[0,0] = 1
print x.cell[1,1] # output: 0
y.cell[x.cell[0,0], x.cell[0,0]] = 2
print y.cell[1,1] # should be 2, still 0
print x.cell[1,1] # should still be 0, but changed, now 2

A workaround would be to return another object in __get__ instead of self, which remembers the "obj" instance, or a closure, or...
But I don''t really see the point, it''s a lot easier to use another object for .cell (it''s more clear, doesn''t break encapsulation, divides responsabilities...)

class Matrix2x2(object):
def __init__(self):
self.cells = [[0,0], [0,0]]

def __setitem__(self, (row, col), value):
self.cells[row][col] = value

def __getitem__(self, (row, col)):
return self.cells[row][col]

class AClass(object):
def __init__(self):
self.cell = Matrix2x2()
--
Gabriel Genellina


2008年5月15日星期四10 :59:41-0300,Gabriel Genellina

< ga ******* @ yahoo.com.arwrote:
On Thu, 15 May 2008 10:59:41 -0300, "Gabriel Genellina"
<ga*******@yahoo.com.arwrote:

> En Wed,2008年5月14日18:15:41 -0300,David C. Ullrich< du ****** @sprynet.comescribió:
>En Wed, 14 May 2008 18:15:41 -0300, David C. Ullrich <du******@sprynet.comescribió:

>很难用一个问题的形式来表达这个问题...

前几天我看到有人问过一个帖子
关于可覆盖的属性,没有人提供
属性为坏的建议。所以也许我们已经克服了这一点。我认为如果用户不知道它们存在,属性可能会产生不良后果,并认为对象的某个属性只是一个普通的属性。但这几乎适用于任何语言的任何方面。
>Having a hard time phrasing this in the form
of a question...

The other day I saw a thread where someone asked
about overrideable properties and nobody offered
the advice that properties are Bad. So maybe we''ve
got over that. I suppose properties could have
Bad consequences if a user doesn''t know they exist
and think that a certain property of an object is
just an ordinary attribute. But that applies to
almost any aspect of any language.


哪些不良后果你在想什么?


Which "bad consequences" are you thinking of?



没有任何具体的想法 - 我只是在扮演魔鬼的拥护者。
。我见过很多人

这里说属性应该只用于

重构时没有任何解释我可以

看看为什么属性是坏事。我指的是他们想到的任何问题


Didn''t have anything specific in mind - there I was
just playing devil''s advocate. I''ve seen a lot of people
here say things like "properties should only be used
when refactoring" without any explanation that I could
see of why properties were bad things. I was referring
to whatever problems they had in mind.


>除了用户不了解某些操作的复杂性,或者getter / setter非常耗时(在这种情况下我会使用公共的getXXX / setXXX函数来强调某事正在发生,而不仅仅是属性查找)
>Apart from the user not being aware of the complexity of certain operations, or a getter/setter very time-consuming (in that case I''d use public getXXX/setXXX functions instead, to emphasize that "something" is happening, not just an attribute lookup)

>如果一个人来自,例如,对象Pascal(德尔福)
那么属性很难没有。
>If a person comes from, say, Object Pascal (Delphi)
then properties are hard to live without. The


您应该阅读文章Python不是Java。如果你还没有这样做的话。
http://dirtsimple.org/2004/12/python-is-not-java.html



我怀疑你误解了我的观点。我实际上在几年前就读过这篇文章

。多年来一直使用Python。我永远不会混淆

它与OP,我保证(幸运的是我不知道任何Java并且不打算
打算)。我真的没有表达我的意思 - 什么

我应该说更像是如果你习惯了属性

来自一种语言像OP一样,它们似乎是一个非常有用的补充。

Python。


看一下这篇文章似乎有两点是相关的。

(i)我很清楚属性访问链不会像在OP中那样用Python编译掉。


(ii)关于getter和setter是如何使用b $ b邪恶的,并且在

简单属性的情况下将内容包装在属性中也是不好的。是。感谢你指出

,但是我不会这样做 - 使用一个属性,其中一个简单的属性将会是愚蠢的。但是,如果一个简单的属性不能用,那么他们可以比使用明确的getter

和setter好得多。

我开始考虑让自己成为wxPython

网格对象的一个​​更好的界面(对我来说更好看)。可以说


grid [row,col] = value


似乎比
更好更自然>
grid.SetCellValue(row,col,value)


(是的,_that_只是__get(设置)item__,

没有属性需要),就像


window.pos =(x,y)


似乎比
更自然

window.SetPos(x,y);


在这些情况下更改单元格所需的工作

值或窗口位置正在进行使

属性界面的额外开销无关紧要。

I suspect you misunderstood my point there. I actually read that
article years ago. Been using Python for years. I''d never confuse
it with OP, I promise (luckily I don''t know any Java and don''t
intend to). I really didn''t express what I meant very well - what
I should have said was more like "If you''re accustomed to properties
from a language like OP they seem like a very useful addition to
Python".

Looking at the article it seems like two points are relevant.
(i) I''m well aware that chains of attribute accesses don''t
get compiled away in Python the way they do in OP.

(ii) Regarding the bit about how getters and setters are
evil, and it''s also bad to wrap things in properties when
simple attributes would do. Yes. Thanks for pointing
that out, but I wouldn''t do that - using a property where
a simple attribute would do would be stupid. But they
_can_ be much nicer than having to use explicit getters
and setters, in cases where a simple attribute won''t do.

I got started on this thinking about making myself a
nicer interface (nicer-seeming to me) to the wxPython
grid object. Being able to say

grid[row, col] = value

seems much nicer and more natural than

grid.SetCellValue(row, col, value)

(yes, _that_ one is just __get(set)item__,
no property needed), just as

window.pos = (x,y)

seems more natural than

window.SetPos(x,y);

in these cases the work involved in changing the cell
value or the window position is going to make the
extra overhead of the property interface irrelevant.


>有一天我决定我想要OP所谓的索引属性或数组属性。无法弄明白如何使_property_表现出来。
所以我读了一些关于描述符的内容,并且几分钟后我有一个索引属性的东西
这就像属性一样,除了它给了一个索引属性!这太酷了。

为什么?例如,一个矩阵应该有一行[n]
属性允许像

m.row [0] = m.row [1] + m.row [2]

好的,你可以通过将行
作为一个普通的Row对象列表来做_that_。但是接着
你不得不说

m.row [0] =排([1,2,3])

我想要的地方能够说m /row
m.row [0] = [1,2,3]

并自动创建Row。
>other day I decided I wanted what OP calls an
"indexed property" or "array property". Couldn''t
figure out how to make a _property_ behave that way.
So I read a little bit about descriptors, and a
few minutes later I had an indexedproperty thing
that works just like property, except it gives
an indexed property! This is just too cool.

Why? For example, a Matrix should have a row[n]
property allowing things like

m.row[0] = m.row[1] + m.row[2]

Ok, you could do _that_ by just making row
an ordinary list of Row objects. But then
you''d have to say

m.row[0] = Row([1,2,3])

where I want to be able to say

m.row[0] = [1,2,3]

and have the Row created automatically.


在这种情况下,可以使* row *成为具有自定义__getitem __ / __ setitem__的对象。


One could make *row* an object with a custom __getitem__/__setitem__ in this case.



然后[见下文]

But then [see below]


>但我更喜欢尽可能少的魔法在我的对象上:如果它说m.row [0] = [1,2,3]我希望m.row [0]实际上*是*那个列表(只要有可能),而不是任何其他对象从[1,2,3]参数初始化
。 (也许这是对C ++魔术构造函数和如此可怕的事情的一些过度反应...)
>But I prefer to have as little magic as possible on my objects: if it says m.row[0] = [1,2,3] I
expect m.row[0] to actually *be* that list (whenever possible), and not any other object initialized
from the [1,2,3] arguments. (Maybe this is some overreaction against C++ "magic" constructors and such horrible things...)



无论如何 - 这里的想法是m.row [0]将要走路和嘎嘎

就像那个列表一样,但也做其他的事情,但是你可以添加其中两个。


(当你说anobject.aproperty = 2时,你也期望aproperty

是2?但是如果aproperty是一个'不一定是这样的属性' - 这个

对于我的版本来说,对于一般的属性来说似乎是一个很大的争论。

。如果你愿意的话,或者变态。)

Whatever - the idea here is that m.row[0] is going to walk and quack
exactly like that list would, but also do other things that the liist
can''t do, like you can add two of them.

(When you say anobject.aproperty = 2 you also expect aproperty to
be 2? But if aproperty is a property that''s not necessarily so - this
seems like as much an argument against properties in general as
against my version. Or perversion, if you like.)


> _Also_这些索引属性我的Matrix
可以有m.row [j]和m.col [k]看起来完全
与客户端相同 - 我们不希望在内部存储行列表,也将相同的数据存储在列列表中。太酷了。
>_Also_ with these indexed properties my Matrix
can have m.row[j] and m.col[k] that look exactly
the same to a client - we don''t want to store a
list of rows internally and also store the same
data in a list of columns. Too cool.


同样可以实现m.row和m.col是我上面所说的自定义对象。


The same can be achieved having m.row and m.col be custom objects like I said above.


>嗯,这不是一个有效的借口,这里的帖子。
嗯,对,我们走了:任何人看到问题或
下面的indexedproperty实现可能的改进?
>Hmm, none of that''s a valid excuse for a post here.
Um, right, here we go: Anyone see problems or
possible improvements with the implementation
of indexedproperty below?


请注意,属性对象(或indexedproperty)是* class *属性。也就是说,在所有实例之间共享。


Note that the property object (or your indexedproperty) is a *class* attribute. That is, shared among all instances.


> class indexedproperty(object):
def __init __(self,getitem = None,setitem = None):
self.getitem = getitem
self.setitem = setitem

def __get __(self,obj,owner):
self.obj = obj
返回self
>class indexedproperty(object):
def __init__(self, getitem=None, setitem=None):
self.getitem = getitem
self.setitem = setitem

def __get__(self, obj, owner):
self.obj = obj
return self


这是问题所在。你不能存储obj。在自我中因为它在所有实例之间共享。您的示例不会显示任何问题,因为所有属性访问后立即使用相同的对象进行getitem访问。试试这个:

x = AClass()
y = AClass()
x.cell [0,0] = 1
print x.cell [1, 1] #output:0
y.cell [x.cell [0,0],x.cell [0,0]] = 2
打印y.cell [1,1]#应该是2,仍为0
打印x.cell [1,1]#应该仍为0,但已更改,现在为2


Here is the problem. You can''t store "obj" in "self" because it is shared among all instances. Your examples don''t show any problem because all property accesses are immediately followed by a getitem access using the same object. Try this:

x = AClass()
y = AClass()
x.cell[0,0] = 1
print x.cell[1,1] # output: 0
y.cell[x.cell[0,0], x.cell[0,0]] = 2
print y.cell[1,1] # should be 2, still 0
print x.cell[1,1] # should still be 0, but changed, now 2



Eewps。我确实意识到indexedproperty和indexedproperty。对象将被分享,但我认为这种问题将由

处理。每次调用__get__时self.obj都被重置。我猜不是.b $ b猜不行。


_A_解决方法就是没有indexedproperties

是类属性,而是说self.whatever在__init__中,
indexedproprty(无论如何)。

Eewps. I did realize that the "indexedproperty" object was going to be
shared, but I thought this sort of problem would be taken care of by
the fact that self.obj was reset each time __get__ was called. I
guess not.

_A_ workaround would be to simply not have indexedproperties
be class attributes, instead saying self.whatever =
indexedproprty(whatever) in __init__.


>解决方法是返回__get__中的另一个对象而不是self,它会记住obj实例,或者一个闭包,或者......
但我真的没有看到这一点,使用.cell的另一个对象要容易得多(它更清楚,不是打破封装,划分责任......)

类Matrix2x2(对象):

def __init __(自我):

self.cells = [ [0,0],[0,0]]

def __setitem __(self,(row,col),value):

self.cells [ row] [col] = value


def __getitem __(self,(row,col)):

返回self.cells [row] [col] <类AClass(对象):

def __init __(自我):

self.cell = Matrix2x2()
>A workaround would be to return another object in __get__ instead of self, which remembers the "obj" instance, or a closure, or...
But I don''t really see the point, it''s a lot easier to use another object for .cell (it''s more clear, doesn''t break encapsulation, divides responsabilities...)

class Matrix2x2(object):
def __init__(self):
self.cells = [[0,0], [0,0]]

def __setitem__(self, (row, col), value):
self.cells[row][col] = value

def __getitem__(self, (row, col)):
return self.cells[row][col]

class AClass(object):
def __init__(self):
self.cell = Matrix2x2()



嗯,这样的事情就是我提出

indexedproperty之前的事情。除非我遗漏了之前发生过的事情,否则你上面写的东西是行不通的,因为

self.cell必须知道Matrix2x2创造了什么因此它知道

在修改时要修改的AClass实例。 (不,我们

不能将状态信息留在self.cells中;想想带有row []属性的Matrix的

情况,还有一个col []

属性 - 他们必须修改存储在

拥有矩阵中的数据。)


所以它会必须更像是(未经测试,

我现在没有在这台机器上使用Python)


class Matrix2x2(object):

def __init __(自我,所有者):

self.owner =所有者


def __setitem __(self,(row,col),值):

self.owner.data [row] [col] = value


def __getitem __(self,(row,col)):

返回self.owner.data [row] [col]


class AClass(object):

def __init __(self):

self.cell = Matrix2x2(个体经营)

self.data = [[0,0],[0,0]]


(再次,在这种情况下,它不一定是那样的,

但它确实存在各种属性和现状 t;

就像单元格提供了不同种类的访问

相同的数据,然后这些数据必须存储在AClass中。)


然后那就是indexedproperty的重点;

来回传递数据的代码不需要

用每个属性重写,这已经在indexedproperty

类的实现中完成了

。我意识到我可以只使用对象属性

,但在我看来,indexedproperty

封装了数据传递protcol一次和

所有而不是每次都要重做它。


感谢您的评论,尤其是指出这个错误的
。在此之前,我复制了一个Python

的property实现。必须要看看

而不是想出来确保我得到

吧,然后看看它为什么属性

没有同样的问题...

David C. Ullrich

Well, something like this is where I was before coming up with
the indexedproperty thing. Unless I''m missing something, which
has happened before, what you write above can''t work, because
self.cell has to know what Matrix2x2 created it so it knows
what AClass instance to modify when it''s modified. (No, we
can''t just leave the state information in self.cells; think of the
case of a Matrix with a row[] property and also a col[]
property - they have to be modifying the data stored in
the owning matrix.)

So it would have to be more something like (untested,
I don''t have Python on this machine right now)

class Matrix2x2(object):
def __init__(self, owner):
self.owner = owner

def __setitem__(self, (row, col), value):
self.owner.data[row][col] = value

def __getitem__(self, (row, col)):
return self.owner.data[row][col]

class AClass(object):
def __init__(self):
self.cell = Matrix2x2(self)
self.data = [[0, 0], [0, 0]]

(again, it doesn''t have to be like that in this case,
but it does in the case where various "properties"
like cells are giving different sorts of access to the
same data, which data then has to be stored in AClass.)

And then that''s the point to the indexedproperty;
the code passing data back and forth doesn''t need
to be rewritten with each property, it''s all done
inside the implementation of the indexedproperty
class. I realized that I could just use object attributes
instead, but it seems to me that indexedproperty
encapsulates the data-passing protcol once and for
all instead of requiring it to be redone each time.

Thanks for the comments, especially for pointing out
the bug. Before doing this I reproduced a Python
implementation of "property". Gonna have to look
that up instead of figuring it out to make sure I got
it right, then look at it to see why property
doesn''t have the same problem...
David C. Ullrich


这篇关于“索引属性”......的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆