等值对象的最佳实践实现 [英] Best practise implementation for equal by value objects

查看:48
本文介绍了等值对象的最佳实践实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我是新来的并且对Python来说相对较新,所以请保持温和:


是否有推荐的通用实现__repr__用于对象

等于值以确保eval(repr(x))== x独立于哪个

模块进行调用?


例如:


类年龄:


def __init __(self,an_age):

self.age = an_age


def __eq __(self,obj):

self.age == obj.age

def __repr __(自我):

返回self .__ class __.__ name__ + \

"(%r)" %self.age


age_ten =年龄(10)

print repr(age_ten)

print eval(repr(age_ten) )

打印eval(repr(age_ten))。年龄


运行此项给出


年龄(10)

年龄(10)
$ b $ 10 10


正如我想要的那样。


当Age类被引入另一个模块时出现问题

在另一个包中,因为有一个包前缀,而__repr__的上述

实现不起作用。


然后我尝试做了类似的事情


def __repr __(自我):

返回self .__ module__ + ''。''+ + self .__ class __.__ name__ +

"(%r)" %self.age


这似乎从外部调用时起作用,但不是来自模块内部的

。也就是说,如果我重新运行上面的脚本

模块名称前缀为表示我得到以下错误


Traceback(最近一次调用最后一次):

文件" valuetest.py",第15行,< module>

print eval(repr(age_ten))

__main__。年龄(10)

文件"< string>",第1行,< module>

NameError:name''__ main__''未定义


这很烦人。


我的问题是:是否有一个强大的通用类型的实现

__repr__我可以使用它吗?


这是我计划重复使用的许多不同的Value类,所以

我想让它变得健壮。


谢谢,

Slaunger

解决方案




Slaunger写道:





我是新来的,相对较新的Python ,请保持温和:


对于对象是否有推荐的__repr__通用实现

等于值以确保eval(repr(x))== x独立的

模块来自哪个电话?



CPython实现放弃了这个目标,只需在地址上打印

< modname.classname对象,至少有两个原因;-) 。


1.一般来说,它需要对__init__进行相当复杂的分析才能确定要包含哪些属性的表示并决定是否

目标甚至是可能的。如果属性是用户

类的实例,则需要分析* * * __init__。如果属性是

模块,类或函数,则没有通用的可评估表示。


2.是否eval(repr(x))甚至work(返回答案)取决于

是否将全局变量和本地变量中的名称绑定传递给eval

(默认情况下是全局变量和本地变量的上下文eval

call)匹配repr中使用的名称。您发现第一个

近似值,这取决于对包含类定义的模块内部或不包含类型定义的模块的调用是否来自

。但

的情况要糟糕得多。考虑''将somemod导入为m''。即使你

能够反省这个电话,并确定它不是来自

somemod **,还要先将''somemod。''添加到repr *仍然*无法工作。

或者,对repr的调用可以来自一个上下文,结果保存并且

传递给具有不同名称绑定的另一个上下文,并且eval

在那里打电话。因此,在任何情况下都可以评估的repr是没有希望的。


如果这是一个实际问题而不是理论问题,那么首先使用你的

repr版本使用类定义名称,只有eval

结果在一个上下文中,该名称绑定到类对象。


from mymod import Age

#or

导入mymod

年龄= mymod.Age


#in无论哪种情况

eval(repr(年龄(10)))==年龄(10)


class年龄:


def __init __(self,an_age):

self.age = an_age


def __eq __(self,obj):

self.age == obj.age


def __repr __(自我):

返回self .__ class __.__ name__ + \

"(%r)" %self.age



**

虽然这种内省不是语言的一部分,但我相信一个

可以在CPython中做到,但我忘记了细节。已经有了'b $ b'这样的线程,比如''如何确定调用者函数''以及

这个问题的答案,我认为调用者的模块也是可用的。


Terry Jan Reedy




周三,2008-08-06在05:50 -0700,Slaunger写道:





我是新来的,相对较新的Python,所以请保持温和:


对于对象是否有推荐的__repr__通用实现

等于值以确保eval(repr(x))== x独立的

模块来自哪个?


示例:


class年龄:


def __init __(self,an_age):

self.age = an_age


def __eq __(self,obj):

self.age == obj.age


def __repr __(自我):

返回self .__ class __.__ name__ + \\ \\ b
"(%R)" %self.age


age_ten =年龄(10)

print repr(age_ten)

print eval(repr(age_ten) )

打印eval(repr(age_ten))。年龄


运行此项给出


年龄(10)

年龄(10)
$ b $ 10 10


正如我想要的那样。


当Age类被引入另一个模块时出现问题

在另一个包中,因为有一个包前缀,而__repr__的上述

实现不起作用。


然后我尝试做了类似的事情


def __repr __(自我):

返回self .__ module__ + ''。''+ + self .__ class __.__ name__ +

"(%r)" %self.age


这似乎从外部调用时起作用,但不是来自模块内部的

。也就是说,如果我重新运行上面的脚本

模块名称前缀为表示我得到以下错误


Traceback(最近一次调用最后一次):

文件" valuetest.py",第15行,< module>

print eval(repr(age_ten))

__main__。年龄(10)

文件"< string>",第1行,< module>

NameError:name''__ main__''未定义


这很烦人。


我的问题是:是否有一个强大的通用类型的实现

__repr__我可以使用它吗?


这是我计划重复使用的许多不同的Value类,所以

我想让它变得健壮。


谢谢,

Slaunger

-
http://mail.python.org/mailman/listinfo/python-list



你呢我确定这就是你想要做的事情,并且一个不那么棘手的

序列化格式,例如pickle模块提供的格式,不会为你工作吗?


-

John Krukoff< jk ****** @ ltgc.com>

土地所有权担保公司


2008年8月6日星期三05:50:35 -0700,Slaunger写道:





我是新来的并且对Python来说比较新,所以请保持温和:


是否有推荐的__repr__通用实现对象

等于值,以确保eval(repr(x))== x independentt of the

模块来自哪个?



一般来说,没有。


....


我的问题是:是否有一个强大的通用类型的实现

__repr__我可以使用它?


这是我计划重用的东西对于许多不同的价值类别,所以我希望b $ b能够让它变得健壮。



我怀疑你能不能把它变得那么健壮,也不打算这样做。


eval(repr(obj)给予obj意味着作为指导,而不是一个不变的 -

有许多东西可以打破它。例如,这里是一个模块

,带有一个简单的类:

#Parrot模块

类Parrot(对象):

def __repr __(self):

return" parrot.Parrot()"

def __eq __(self,other):

#所有鹦鹉都是平等的

返回isinstance(其他,Parrot)

现在让我们使用它:


>> import parrot
p = parrot.Parrot()
s = repr(p)
断言eval(s)== p
del parrot
断言eval(s)== p



追溯(最近一次呼叫最后一次):

文件"< stdin>",第1行,< module>

文件"< string> ",第1行,在< module>

NameError:name''parrot''未定义

如果查看标准库中的类,它们通常是有这样的代表


< blockquote class =post_quotes>


>> repr(timeit.Timer())



''< timeit.Timer实例位于0xb7f14bcc>''


当然你不能期望成功评估它!


我相信eval(repr(obj))再次给obj的建议是

意味着交互式解释器的便利,甚至还有

仅适用于int或list等简单类型。如果你能做到这一点,那很好,但是如果它不起作用,那就这样吧。你不应该依赖它,并且它是

并不是一般序列化类的方法。

-

史蒂文


Hi,

I am new here and relatively new to Python, so be gentle:

Is there a recommended generic implementation of __repr__ for objects
equal by value to assure that eval(repr(x)) == x independet of which
module the call is made from?

Example:

class Age:

def __init__(self, an_age):
self.age = an_age

def __eq__(self, obj):
self.age == obj.age

def __repr__(self):
return self.__class__.__name__ + \
"(%r)" % self.age

age_ten = Age(10)
print repr(age_ten)
print eval(repr(age_ten))
print eval(repr(age_ten)).age

Running this gives

Age(10)
Age(10)
10

Exactly as I want to.

The problem arises when the Age class is iomported into another module
in another package as then there is a package prefix and the above
implementation of __repr__ does not work.

I have then experimented with doing somthing like

def __repr__(self):
return self.__module__ + ''.'' + self.__class__.__name__ +
"(%r)" % self.age

This seems to work when called from the outside, but not from the
inside of the module. That is, if I rerun the script above the the
module name prefixed to the representation I get the following error

Traceback (most recent call last):
File "valuetest.py", line 15, in <module>
print eval(repr(age_ten))
__main__.Age(10)
File "<string>", line 1, in <module>
NameError: name ''__main__'' is not defined

This is pretty annoying.

My question is: Is there a robust generic type of implementation of
__repr__ which I can use instead?

This is something I plan to reuse for many different Value classes, so
I would like to get it robust.

Thanks,
Slaunger

解决方案



Slaunger wrote:

Hi,

I am new here and relatively new to Python, so be gentle:

Is there a recommended generic implementation of __repr__ for objects
equal by value to assure that eval(repr(x)) == x independet of which
module the call is made from?

The CPython implementation gives up on that goal and simply prints
<modname.classname object at addressfor at least two reasons ;-).

1. In general, it require fairly sophisticated analysis of __init__ to
decide what representation of what attributes to include and decide if
the goal is even possible. If an attribute is an instance of a user
class, then *its* __init__ needs to be analyzed. If an attribute is a
module, class, or function, there is no generic evaluable representation.

2. Whether eval(repr(x)) even works (returns an answer) depends on
whether the name bindings in the globals and locals passed to eval
(which by default are the globals and locals of the context of the eval
call) match the names used in the repr. You discovered that to a first
approximation, this depends on whether the call to repr comes from
within or without the module containing the class definition. But the
situation is far worse. Consider ''import somemod as m''. Even if you
were able to introspect the call and determine that it did not come from
somemod**, prepending ''somemod.'' to the repr *still* would not work.
Or, the call to repr could come from one context, the result saved and
passed to another context with different name bindings, and the eval
call made there. So an repr that can be eval''ed in any context is hopeless.

If this is a practical rather than theoretical question, then use your
first repr version that uses the classes definition name and only eval
the result in a context that has that name bound to the class object.

from mymod import Age
#or
import mymod
Age = mymod.Age

#in either case
eval(repr(Age(10))) == Age(10)

class Age:

def __init__(self, an_age):
self.age = an_age

def __eq__(self, obj):
self.age == obj.age

def __repr__(self):
return self.__class__.__name__ + \
"(%r)" % self.age

**
While such introspection is not part of the language, I believe one
could do it in CPython, but I forgot the details. There have been
threads like ''How do I determine the caller function'' with answers to
that question, and I presume the module of the caller is available also.

Terry Jan Reedy



On Wed, 2008-08-06 at 05:50 -0700, Slaunger wrote:

Hi,

I am new here and relatively new to Python, so be gentle:

Is there a recommended generic implementation of __repr__ for objects
equal by value to assure that eval(repr(x)) == x independet of which
module the call is made from?

Example:

class Age:

def __init__(self, an_age):
self.age = an_age

def __eq__(self, obj):
self.age == obj.age

def __repr__(self):
return self.__class__.__name__ + \
"(%r)" % self.age

age_ten = Age(10)
print repr(age_ten)
print eval(repr(age_ten))
print eval(repr(age_ten)).age

Running this gives

Age(10)
Age(10)
10

Exactly as I want to.

The problem arises when the Age class is iomported into another module
in another package as then there is a package prefix and the above
implementation of __repr__ does not work.

I have then experimented with doing somthing like

def __repr__(self):
return self.__module__ + ''.'' + self.__class__.__name__ +
"(%r)" % self.age

This seems to work when called from the outside, but not from the
inside of the module. That is, if I rerun the script above the the
module name prefixed to the representation I get the following error

Traceback (most recent call last):
File "valuetest.py", line 15, in <module>
print eval(repr(age_ten))
__main__.Age(10)
File "<string>", line 1, in <module>
NameError: name ''__main__'' is not defined

This is pretty annoying.

My question is: Is there a robust generic type of implementation of
__repr__ which I can use instead?

This is something I plan to reuse for many different Value classes, so
I would like to get it robust.

Thanks,
Slaunger
--
http://mail.python.org/mailman/listinfo/python-list

Are you really sure this is what you want to do, and that a less tricky
serialization format such as that provided by the pickle module wouldn''t
work for you?

--
John Krukoff <jk******@ltgc.com>
Land Title Guarantee Company


On Wed, 06 Aug 2008 05:50:35 -0700, Slaunger wrote:

Hi,

I am new here and relatively new to Python, so be gentle:

Is there a recommended generic implementation of __repr__ for objects
equal by value to assure that eval(repr(x)) == x independet of which
module the call is made from?

In general, no.

....

My question is: Is there a robust generic type of implementation of
__repr__ which I can use instead?

This is something I plan to reuse for many different Value classes, so I
would like to get it robust.

I doubt you could get it that robust, nor is it intended to be.

eval(repr(obj)) giving obj is meant as a guideline, not an invariant --
there are many things that can break it. For example, here''s a module
with a simple class:
# Parrot module
class Parrot(object):
def __repr__(self):
return "parrot.Parrot()"
def __eq__(self, other):
# all parrots are equal
return isinstance(other, Parrot)
Now let''s use it:

>>import parrot
p = parrot.Parrot()
s = repr(p)
assert eval(s) == p
del parrot
assert eval(s) == p

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name ''parrot'' is not defined
If you look at classes in the standard library, they often have reprs
like this:

>>repr(timeit.Timer())

''<timeit.Timer instance at 0xb7f14bcc>''

Certainly you can''t expect to successfully eval that!

I believe the recommendation for eval(repr(obj)) to give obj again is
meant as a convenience for the interactive interpreter, and even there
only for simple types like int or list. If you can do it, great, but if
it doesn''t work, so be it. You''re not supposed to rely on it, and it''s
not meant as a general way to serialize classes.
--
Steven


这篇关于等值对象的最佳实践实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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