标签归档:repr

访问对象存储器地址

问题:访问对象存储器地址

当您object.__repr__()在Python中调用该方法时,您会得到类似以下的信息:

<__main__.Test object at 0x2aba1c0cf890> 

如果您过载了__repr__(),还有什么方法可以保留该内存地址,然后调用super(Class, obj).__repr__()并重新分配它呢?

When you call the object.__repr__() method in Python you get something like this back:

<__main__.Test object at 0x2aba1c0cf890> 

Is there any way to get a hold of the memory address if you overload __repr__(), other then calling super(Class, obj).__repr__() and regexing it out?


回答 0

Python的手册已经这样说id()

返回一个对象的“身份”,这是一个整数(或长整数),在该对象的生存期内保证是唯一且恒定的。两个不重叠生存期的对象可能具有相同的id()值。 (实施说明:这是对象的地址。)

因此,在CPython中,这将是对象的地址。但是,没有任何其他Python解释器的此类保证。

请注意,如果您正在编写C扩展名,则可以完全访问Python解释器的内部,包括直接访问对象的地址。

The Python manual has this to say about id():

Return the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value. (Implementation note: this is the address of the object.)

So in CPython, this will be the address of the object. No such guarantee for any other Python interpreter, though.

Note that if you’re writing a C extension, you have full access to the internals of the Python interpreter, including access to the addresses of objects directly.


回答 1

您可以通过以下方式重新实现默认代表:

def __repr__(self):
    return '<%s.%s object at %s>' % (
        self.__class__.__module__,
        self.__class__.__name__,
        hex(id(self))
    )

You could reimplement the default repr this way:

def __repr__(self):
    return '<%s.%s object at %s>' % (
        self.__class__.__module__,
        self.__class__.__name__,
        hex(id(self))
    )

回答 2

只需使用

id(object)

Just use

id(object)

回答 3

这里有一些其他答案未涵盖的问题。

首先,id仅返回:

对象的“身份”。这是一个整数(或长整数),在该对象的生存期内,此整数保证是唯一且恒定的。具有非重叠生存期的两个对象可能具有相同的id()值。


在CPython中,这恰好是指向PyObject解释器中代表对象的指针,这与on上的东西相同,显然不会成为指针。我不确定IronPython,但我怀疑在这方面,它更像是Jython,而不是CPython。因此,在大多数Python实现中,无法获得显示在其中的任何内容,如果您这样做了,则毫无用处。object.__repr__显示。但这只是CPython的实现细节,而不是一般Python的真实情况。Jython不处理指针,它处理Java引用(JVM当然可以将其表示为指针,但是您看不到它们,并且也不想这样做,因为允许GC来回移动它们)。PyPy让不同类型的对象具有不同的种类id,但最一般的只是对您已调用的对象表的索引idrepr


但是,如果您只关心CPython怎么办?毕竟,这是一个很普通的情况。

好吧,首先,您可能会注意到这id是一个整数; *如果您想要该0x2aba1c0cf890字符串而不是数字46978822895760,则必须自己设置其格式。在幕后,我相信object.__repr__最终使用printf%p格式,你没有从Python的有……但你总是可以做到这一点:

format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')

*在3.x中,它是一个int。在2.x中,int如果它足够大以容纳一个指针(可能不是由于某些平台上的有符号数问题而引起的),long否则是一个错误。

除了将它们打印出来,您还能使用这些指针做什么?当然(再次假设您只关心CPython)。

所有C API函数均采用指向PyObject或相关类型的指针。对于那些相关的类型,您可以调用PyFoo_Check以确保它确实是一个Foo对象,然后使用进行强制转换(PyFoo *)p。因此,如果您要编写C扩展名,id则正是您所需要的。

如果您正在编写纯Python代码怎么办?您可以使用pythonapifrom 调用完全相同的函数ctypes


最后,提出了其他一些答案ctypes.addressof。这与这里无关。这仅适用于ctypes类似的对象c_int32(可能还有一些类似内存缓冲区的对象,如所提供的对象numpy)。而且,即使在那儿,它也没有为您提供c_int32值的地址,而是为您提供int32c_int32包装的C级地址。

话虽这么说,但通常情况下,如果您确实认为自己需要某个东西的地址,那么首先就不需要原生Python对象,而是想要一个ctypes对象。

There are a few issues here that aren’t covered by any of the other answers.

First, id only returns:

the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.


In CPython, this happens to be the pointer to the PyObject that represents the object in the interpreter, which is the same thing that object.__repr__ displays. But this is just an implementation detail of CPython, not something that’s true of Python in general. Jython doesn’t deal in pointers, it deals in Java references (which the JVM of course probably represents as pointers, but you can’t see those—and wouldn’t want to, because the GC is allowed to move them around). PyPy lets different types have different kinds of id, but the most general is just an index into a table of objects you’ve called id on, which is obviously not going to be a pointer. I’m not sure about IronPython, but I’d suspect it’s more like Jython than like CPython in this regard. So, in most Python implementations, there’s no way to get whatever showed up in that repr, and no use if you did.


But what if you only care about CPython? That’s a pretty common case, after all.

Well, first, you may notice that id is an integer;* if you want that 0x2aba1c0cf890 string instead of the number 46978822895760, you’re going to have to format it yourself. Under the covers, I believe object.__repr__ is ultimately using printf‘s %p format, which you don’t have from Python… but you can always do this:

format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')

* In 3.x, it’s an int. In 2.x, it’s an int if that’s big enough to hold a pointer—which is may not be because of signed number issues on some platforms—and a long otherwise.

Is there anything you can do with these pointers besides print them out? Sure (again, assuming you only care about CPython).

All of the C API functions take a pointer to a PyObject or a related type. For those related types, you can just call PyFoo_Check to make sure it really is a Foo object, then cast with (PyFoo *)p. So, if you’re writing a C extension, the id is exactly what you need.

What if you’re writing pure Python code? You can call the exact same functions with pythonapi from ctypes.


Finally, a few of the other answers have brought up ctypes.addressof. That isn’t relevant here. This only works for ctypes objects like c_int32 (and maybe a few memory-buffer-like objects, like those provided by numpy). And, even there, it isn’t giving you the address of the c_int32 value, it’s giving you the address of the C-level int32 that the c_int32 wraps up.

That being said, more often than not, if you really think you need the address of something, you didn’t want a native Python object in the first place, you wanted a ctypes object.


回答 4

仅作为对Torsten的回应,我无法调用addressof()常规的python对象。此外,id(a) != addressof(a)。这是在CPython中,对其他什么都不知道。

>>> from ctypes import c_int, addressof
>>> a = 69
>>> addressof(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: invalid type
>>> b = c_int(69)
>>> addressof(b)
4300673472
>>> id(b)
4300673392

Just in response to Torsten, I wasn’t able to call addressof() on a regular python object. Furthermore, id(a) != addressof(a). This is in CPython, don’t know about anything else.

>>> from ctypes import c_int, addressof
>>> a = 69
>>> addressof(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: invalid type
>>> b = c_int(69)
>>> addressof(b)
4300673472
>>> id(b)
4300673392

回答 5

使用ctypes,您可以使用

>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L

说明文件:

addressof(C instance) -> integer
返回C实例内部缓冲区的地址

请注意,在CPython中,当前是id(a) == ctypes.addressof(a),但是ctypes.addressof应返回每个Python实现的真实地址,如果

  • 支持ctypes
  • 内存指针是一个有效的概念。

编辑:添加了有关ctypes解释器独立性的信息

With ctypes, you can achieve the same thing with

>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L

Documentation:

addressof(C instance) -> integer
Return the address of the C instance internal buffer

Note that in CPython, currently id(a) == ctypes.addressof(a), but ctypes.addressof should return the real address for each Python implementation, if

  • ctypes is supported
  • memory pointers are a valid notion.

Edit: added information about interpreter-independence of ctypes


回答 6

您可以通过以下方式获得适合该目的的东西:

id(self)

You can get something suitable for that purpose with:

id(self)

回答 7

我知道这是一个老问题,但是如果您现在仍在使用python 3编程,我实际上发现如果它是字符串,那么有一种非常简单的方法可以做到这一点:

>>> spam.upper
<built-in method upper of str object at 0x1042e4830>
>>> spam.upper()
'YO I NEED HELP!'
>>> id(spam)
4365109296

字符串转换也不影响内存中的位置:

>>> spam = {437 : 'passphrase'}
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
>>> str(spam)
"{437: 'passphrase'}"
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'

I know this is an old question but if you’re still programming, in python 3 these days… I have actually found that if it is a string, then there is a really easy way to do this:

>>> spam.upper
<built-in method upper of str object at 0x1042e4830>
>>> spam.upper()
'YO I NEED HELP!'
>>> id(spam)
4365109296

string conversion does not affect location in memory either:

>>> spam = {437 : 'passphrase'}
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
>>> str(spam)
"{437: 'passphrase'}"
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'

回答 8

虽然确实id(object)可以在默认的CPython实现中获取对象的地址,但这通常是无用的……您无法纯Python代码中的地址进行任何操作。

实际上,唯一可以使用该地址的时间是来自C扩展库…在这种情况下,获取对象的地址很简单,因为Python对象始终作为C指针传递。

While it’s true that id(object) gets the object’s address in the default CPython implementation, this is generally useless… you can’t do anything with the address from pure Python code.

The only time you would actually be able to use the address is from a C extension library… in which case it is trivial to get the object’s address since Python objects are always passed around as C pointers.


了解Python中的repr()函数

问题:了解Python中的repr()函数

repr():对象的可评估字符串表示形式(可以“ eval()”表示它,这是一个评估为Python对象的字符串表示形式)

换一种说法:

>>> x = 'foo'
>>> repr(x)
"'foo'"

问题:

  1. 为什么我得到双引号repr(x)?(这样做的时候我不懂str(x)
  2. 为什么我会'foo'当我做eval("'foo'"),而不是X也就是对象?

repr(): evaluatable string representation of an object (can “eval()” it, meaning it is a string representation that evaluates to a Python object)

In other words:

>>> x = 'foo'
>>> repr(x)
"'foo'"

Questions:

  1. Why do I get the double quotes when I do repr(x)? (I don’t get them when I do str(x))
  2. Why do I get 'foo' when I do eval("'foo'") and not x which is the object?

回答 0

>>> x = 'foo'
>>> x
'foo'

因此,名称x将附加到'foo'字符串。例如repr(x),当您调用时,解释器放'foo'而不是,x然后调用repr('foo')

>>> repr(x)
"'foo'"
>>> x.__repr__()
"'foo'"

repr实际调用一个魔术方法__repr__x,这给包含该值的表示'foo'分配给x。因此它会'foo'在字符串内返回""结果"'foo'"。的想法repr是给出一个包含一系列符号的字符串,我们可以在解释器中键入该符号,并获得与作为参数发送给的相同值repr

>>> eval("'foo'")
'foo'

调用时eval("'foo'"),与'foo'在解释器中键入的相同。就像我们""在解释器中直接键入外部字符串的内容一样。

>>> eval('foo')

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    eval('foo')
  File "<string>", line 1, in <module>
NameError: name 'foo' is not defined

如果调用eval('foo'),则与foo在解释器中键入的相同。但是没有foo可用的变量,并且引发了异常。

>>> str(x)
'foo'
>>> x.__str__()
'foo'
>>> 

str只是对象的字符串表示形式(请记住,x变量是指'foo'),因此此函数返回字符串。

>>> str(5)
'5'

整数的字符串表示形式5'5'

>>> str('foo')
'foo'

并且字符串的字符串表示形式'foo'是相同的字符串'foo'

>>> x = 'foo'
>>> x
'foo'

So the name x is attached to 'foo' string. When you call for example repr(x) the interpreter puts 'foo' instead of x and then calls repr('foo').

>>> repr(x)
"'foo'"
>>> x.__repr__()
"'foo'"

repr actually calls a magic method __repr__ of x, which gives the string containing the representation of the value 'foo' assigned to x. So it returns 'foo' inside the string "" resulting in "'foo'". The idea of repr is to give a string which contains a series of symbols which we can type in the interpreter and get the same value which was sent as an argument to repr.

>>> eval("'foo'")
'foo'

When we call eval("'foo'"), it’s the same as we type 'foo' in the interpreter. It’s as we directly type the contents of the outer string "" in the interpreter.

>>> eval('foo')

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    eval('foo')
  File "<string>", line 1, in <module>
NameError: name 'foo' is not defined

If we call eval('foo'), it’s the same as we type foo in the interpreter. But there is no foo variable available and an exception is raised.

>>> str(x)
'foo'
>>> x.__str__()
'foo'
>>> 

str is just the string representation of the object (remember, x variable refers to 'foo'), so this function returns string.

>>> str(5)
'5'

String representation of integer 5 is '5'.

>>> str('foo')
'foo'

And string representation of string 'foo' is the same string 'foo'.


回答 1

您在交互式解释器上获得的反馈也将使用repr。当您键入表达式(顺便说一句expr)时,解释器基本上会执行result = expr; if result is not None: print repr(result)。因此,在您的例子中,第二行格式化字符串foo为表示你要('foo')。然后解释创建repr的esentation ,让你用双引号。

为什么当我将%r与双引号和单引号转义结合使用并打印出来时,它以我将其写入.py文件的方式而不是我希望看到的方式打印出来?

我不确定您在这里问什么。文本single ' and double " quotes在运行时repr,包含一种引号的转义符。当然可以,否则Python规则将不是有效的字符串文字。这正是您要求通过调用repr

还要注意,eval(repr(x)) == x类推并非字面意思。这是一个近似值,适用于大多数(所有?)内置类型,但主要的是,通过查看repr输出,您可以很好地了解类型和逻辑“值” 。

The feedback you get on the interactive interpreter uses repr too. When you type in an expression (let it be expr), the interpreter basically does result = expr; if result is not None: print repr(result). So the second line in your example is formatting the string foo into the representation you want ('foo'). And then the interpreter creates the representation of that, leaving you with double quotes.

Why when I combine %r with double-quote and single quote escapes and print them out, it prints it the way I’d write it in my .py file but not the way I’d like to see it?

I’m not sure what you’re asking here. The text single ' and double " quotes, when run through repr, includes escapes for one kind of quote. Of course it does, otherwise it wouldn’t be a valid string literal by Python rules. That’s precisely what you asked for by calling repr.

Also note that the eval(repr(x)) == x analogy isn’t meant literal. It’s an approximation and holds true for most (all?) built-in types, but the main thing is that you get a fairly good idea of the type and logical “value” from looking the the repr output.


回答 2

str()用于为最终用户创建输出,而repr()用于调试开发,它代表对象的正式名称。

例:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2018-04-08 18:00:15.178404'
>>> repr(today)
'datetime.datetime(2018, 4, 8, 18, 3, 21, 167886)'

从输出中我们看到repr()显示了date对象的正式表示形式。

str() is used for creating output for end user while repr() is used for debuggin development.And it’s represent the official of object.

Example:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2018-04-08 18:00:15.178404'
>>> repr(today)
'datetime.datetime(2018, 4, 8, 18, 3, 21, 167886)'

From output we see that repr() shows the official representation of date object.


回答 3

1)的结果repr('foo')字符串 'foo'。在您的Python Shell中,表达式的结果也被表示为表示形式,因此您基本上可以看到repr(repr('foo'))

2)eval计算表达式的结果。结果始终是一个(例如数字,字符串或对象)。多个变量可以引用相同的值,如下所示:

x = 'foo'
y = x

x和y现在引用相同的值。

3)我不知道你在这里是什么意思。您可以发表一个例子,以及您想看到的内容吗?

1) The result of repr('foo') is the string 'foo'. In your Python shell, the result of the expression is expressed as a representation too, so you’re essentially seeing repr(repr('foo')).

2) eval calculates the result of an expression. The result is always a value (such as a number, a string, or an object). Multiple variables can refer to the same value, as in:

x = 'foo'
y = x

x and y now refer to the same value.

3) I have no idea what you meant here. Can you post an example, and what you’d like to see?


回答 4

当你说

foo = 'bar'
baz(foo)

您没有传递foo给该baz函数。 foo在这种情况下'bar',只是一个用于表示值的名称,该值将传递给baz函数。

When you say

foo = 'bar'
baz(foo)

you are not passing foo to the baz function. foo is just a name used to represent a value, in this case 'bar', and that value is passed to the baz function.


__str__和__repr__之间的区别?

问题:__str__和__repr__之间的区别?

__str____repr__Python 和有什么不一样?

What is the difference between __str__ and __repr__ in Python?


回答 0

亚历克斯总结得很好,但令人惊讶的是,它太简洁了。

首先,让我重申亚历克斯(Alex)帖子中的要点:

  • 默认的实现是无用的(很难想到不会的,但是是的)
  • __repr__ 目标是明确
  • __str__ 目标是可读
  • 容器__str__使用的包含对象__repr__

默认实现是没有用的

这主要是令人惊讶的,因为Python的默认设置往往非常有用。但是,在这种情况下,具有默认值的__repr__行为如下:

return "%s(%r)" % (self.__class__, self.__dict__)

太危险了(例如,如果对象之间互相引用,则很容易陷入无限递归)。因此,Python应对了。请注意,有一个默认值为true:如果__repr__已定义,但未定义,__str__则该对象的行为就好像__str__=__repr__

简单来说,这意味着:您实现的几乎每个对象都应具有__repr__可用于理解该对象的功能。实施__str__是可选的:如果您需要“漂亮的打印”功能(例如,由报告生成器使用),请执行此操作。

的目标__repr__是明确的

我马上说出来-我不相信调试器。我真的不知道如何使用任何调试器,也从未认真使用过。此外,我相信调试器的最大缺陷是它们的基本特性–我调试的大多数故障是很久以前发生的,它位于一个遥远的星系中。这意味着我确实以宗教的热情相信伐木。日志记录是任何体面的“一劳永逸”服务器系统的命脉。使用Python可以轻松记录日志:也许有一些特定于项目的包装器,您只需要一个

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

但是,您必须做最后一步-确保实现的每个对象都有一个有用的代表,这样的代码才能正常工作。这就是为什么出现“评估”问题的原因:如果您有足够的信息eval(repr(c))==c,这意味着您知道所有要了解的信息c。如果那很容易(至少以一种模糊的方式),那就去做。如果没有,请确保您有足够的信息c。我通常使用类似eval的格式:"MyClass(this=%r,that=%r)" % (self.this,self.that)。这并不意味着您可以实际构造MyClass,也不意味着它们是正确的构造方法参数—但这是表达“这是您需要了解的有关该实例的一切”的有用形式。

注意:我在%r上面使用过,不是%s。您总是想在实现中使用repr()[或%r等效地格式化字符] __repr__,否则您就无法实现repr的目标。你要能够区分MyClass(3)MyClass("3")

的目标__str__是可读

具体来说,它并非旨在明确-请注意str(3)==str("3")。同样,如果实现IP抽象,则让其str看起来像192.168.1.1很好。在实现日期/时间抽象时,str可以是“ 2010/4/12 15:35:22”,等等。目标是以用户(而不是程序员)想要阅读的方式表示它。砍掉无用的数字,冒充其他类别-只要它支持可读性,它就是一种进步。

容器__str__使用的包含对象__repr__

这似乎令人惊讶,不是吗?它有点,但是如果使用它们,它们的可读性如何__str__

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

不是特别的。具体而言,容器中的字符串会发现太容易打乱其字符串表示形式。记住,面对歧义,Python抵制了猜测的诱惑。如果您在打印列表时需要上述行为,则只需

print "[" + ", ".join(l) + "]"

(您可能还可以弄清楚如何处理字典。

摘要

实现__repr__你实现任何类。这应该是第二天性。__str__如果您认为有一个字符串版本会影响可读性会很有用,请实施。

Alex summarized well but, surprisingly, was too succinct.

First, let me reiterate the main points in Alex’s post:

  • The default implementation is useless (it’s hard to think of one which wouldn’t be, but yeah)
  • __repr__ goal is to be unambiguous
  • __str__ goal is to be readable
  • Container’s __str__ uses contained objects’ __repr__

Default implementation is useless

This is mostly a surprise because Python’s defaults tend to be fairly useful. However, in this case, having a default for __repr__ which would act like:

return "%s(%r)" % (self.__class__, self.__dict__)

would have been too dangerous (for example, too easy to get into infinite recursion if objects reference each other). So Python cops out. Note that there is one default which is true: if __repr__ is defined, and __str__ is not, the object will behave as though __str__=__repr__.

This means, in simple terms: almost every object you implement should have a functional __repr__ that’s usable for understanding the object. Implementing __str__ is optional: do that if you need a “pretty print” functionality (for example, used by a report generator).

The goal of __repr__ is to be unambiguous

Let me come right out and say it — I do not believe in debuggers. I don’t really know how to use any debugger, and have never used one seriously. Furthermore, I believe that the big fault in debuggers is their basic nature — most failures I debug happened a long long time ago, in a galaxy far far away. This means that I do believe, with religious fervor, in logging. Logging is the lifeblood of any decent fire-and-forget server system. Python makes it easy to log: with maybe some project specific wrappers, all you need is a

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

But you have to do the last step — make sure every object you implement has a useful repr, so code like that can just work. This is why the “eval” thing comes up: if you have enough information so eval(repr(c))==c, that means you know everything there is to know about c. If that’s easy enough, at least in a fuzzy way, do it. If not, make sure you have enough information about c anyway. I usually use an eval-like format: "MyClass(this=%r,that=%r)" % (self.this,self.that). It does not mean that you can actually construct MyClass, or that those are the right constructor arguments — but it is a useful form to express “this is everything you need to know about this instance”.

Note: I used %r above, not %s. You always want to use repr() [or %r formatting character, equivalently] inside __repr__ implementation, or you’re defeating the goal of repr. You want to be able to differentiate MyClass(3) and MyClass("3").

The goal of __str__ is to be readable

Specifically, it is not intended to be unambiguous — notice that str(3)==str("3"). Likewise, if you implement an IP abstraction, having the str of it look like 192.168.1.1 is just fine. When implementing a date/time abstraction, the str can be “2010/4/12 15:35:22”, etc. The goal is to represent it in a way that a user, not a programmer, would want to read it. Chop off useless digits, pretend to be some other class — as long is it supports readability, it is an improvement.

Container’s __str__ uses contained objects’ __repr__

This seems surprising, doesn’t it? It is a little, but how readable would it be if it used their __str__?

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

Not very. Specifically, the strings in a container would find it way too easy to disturb its string representation. In the face of ambiguity, remember, Python resists the temptation to guess. If you want the above behavior when you’re printing a list, just

print "[" + ", ".join(l) + "]"

(you can probably also figure out what to do about dictionaries.

Summary

Implement __repr__ for any class you implement. This should be second nature. Implement __str__ if you think it would be useful to have a string version which errs on the side of readability.


回答 1

我的经验法则: __repr__针对开发人员,__str__针对客户。

My rule of thumb: __repr__ is for developers, __str__ is for customers.


回答 2

除非您特别采取行动以确保其他情况,否则大多数类在以下两个方面均不会产生有用的结果:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

如您所见-没有区别,没有信息超出类和对象的id。如果仅覆盖两个…之一:

>>> class Sic(object): 
...   def __repr__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>> 

如您所见,如果您覆盖__repr__,这也用于__str__,但反之则不。

要知道的其他关键要点:__str__在内置容器上__repr__,对包含的项目使用,而不是对__str__。而且,尽管在典型文档中找到了有关主题的字眼,但几乎没有人为使__repr__对象的字符串成为eval可用于构建相等对象的字符串而烦恼(这太难了,而且不知道相关模块的实际导入方式会使它实际上完全不可能)。

因此,我的建议是:着重于使__str__合理的人类可读性,并__repr__尽可能地做到模棱两可,即使这会干扰使__repr__的返回值可以接受为__eval__!的模糊不可实现的目标。

Unless you specifically act to ensure otherwise, most classes don’t have helpful results for either:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

As you see — no difference, and no info beyond the class and object’s id. If you only override one of the two…:

>>> class Sic(object): 
...   def __repr__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>> 

as you see, if you override __repr__, that’s ALSO used for __str__, but not vice versa.

Other crucial tidbits to know: __str__ on a built-on container uses the __repr__, NOT the __str__, for the items it contains. And, despite the words on the subject found in typical docs, hardly anybody bothers making the __repr__ of objects be a string that eval may use to build an equal object (it’s just too hard, AND not knowing how the relevant module was actually imported makes it actually flat out impossible).

So, my advice: focus on making __str__ reasonably human-readable, and __repr__ as unambiguous as you possibly can, even if that interferes with the fuzzy unattainable goal of making __repr__‘s returned value acceptable as input to __eval__!


回答 3

__repr__:python对象的表示形式,通常eval会将其转换回该对象

__str__:是您认为的文本形式的对象

例如

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True

__repr__: representation of python object usually eval will convert it back to that object

__str__: is whatever you think is that object in text form

e.g.

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True

回答 4

简而言之,的目标__repr__是明确且__str__可读。

这是一个很好的例子:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

阅读此文档以获取代表:

repr(object)

返回包含对象的可打印表示形式的字符串。这与转化产生的值相同(反引号)。能够以常规功能访问此操作有时很有用。对于许多类型,此函数会尝试返回一个字符串,该字符串将在传递给时产生一个具有相同值的对象eval(),否则表示形式是一个用尖括号括起来的字符串,其中包含对象类型的名称以及其他信息通常包括对象的名称和地址。类可以通过定义__repr__()方法来控制此函数为其实例返回的内容。

这是str的文档:

str(object='')

返回一个字符串,其中包含对象的可很好打印的表示形式。对于字符串,这将返回字符串本身。与的区别repr(object)在于,str(object)并非总是尝试返回可接受的字符串eval();它的目标是返回可打印的字符串。如果未提供任何参数,则返回空字符串''

In short, the goal of __repr__ is to be unambiguous and __str__ is to be readable.

Here is a good example:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

Read this documentation for repr:

repr(object)

Return a string containing a printable representation of an object. This is the same value yielded by conversions (reverse quotes). It is sometimes useful to be able to access this operation as an ordinary function. For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to eval(), otherwise the representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object. A class can control what this function returns for its instances by defining a __repr__() method.

Here is the documentation for str:

str(object='')

Return a string containing a nicely printable representation of an object. For strings, this returns the string itself. The difference with repr(object) is that str(object) does not always attempt to return a string that is acceptable to eval(); its goal is to return a printable string. If no argument is given, returns the empty string, ''.


回答 5

__str____repr__Python 和有什么不一样?

__str__(读为“ dunder(双下划线)字符串”)和__repr__(读为“ dunder-repper”(对于“表示形式”))都是根据对象状态返回字符串的特殊方法。

__repr__如果__str__丢失,则提供备份行为。

因此,首先应该编写一个__repr__,使您可以从返回的字符串中重新实例化一个等效的对象,例如,使用eval或通过在Python Shell中的逐字符键入字符。

在以后的任何时候,只要__str__有人认为有必要,就可以为该实例的用户可读的字符串表示形式编写一个。

__str__

如果打印对象,或将其传递给formatstr.formatstr,则如果__str__定义了方法,则将调用该方法,否则__repr__将使用该方法。

__repr__

__repr__方法由内置函数调用,repr并且是在评估返回对象的表达式时在python shell上回显的方法。

由于它为提供了备份__str__,如果您只能写一个,请从__repr__

这是关于的内置帮助repr

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

也就是说,对于大多数对象,如果键入所打印的内容repr,则应该能够创建等效对象。但这不是默认的实现。

默认实现 __repr__

默认对象__repr__是(C Python source)类似:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

这意味着默认情况下,您将打印对象所属的模块,类名以及其在内存中位置的十六进制表示形式,例如:

<__main__.Foo object at 0x7f80665abdd0>

这些信息不是很有用,但是无法得出如何准确地创建任何给定实例的规范表示的方法,它总比没有好,至少告诉我们如何在内存中唯一标识它。

怎么__repr__有用?

让我们看看使用Python Shell和datetime对象有多么有用。首先,我们需要导入datetime模块:

import datetime

如果datetime.now在外壳中调用,我们将看到重新创建等效的datetime对象所需的一切。这是由datetime创建的__repr__

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

如果我们打印日期时间对象,则会看到一种很好的人类可读(实际上是ISO)格式。这是通过datetime的实现的__str__

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

重新创建丢失的对象是一件简单的事情,因为我们没有通过复制和粘贴从__repr__输出中将其分配给变量,然后进行打印,然后将其与其他对象存储在相同的人类可读输出中:

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

我该如何实施?

在开发过程中,如果可能的话,您将希望能够以相同状态再现对象。例如,这就是datetime对象的定义方式__repr__Python源)。由于复制此类对象所需的所有属性,它相当复杂:

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day,  # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s

如果希望对象具有更易理解的表示形式,则可以执行__str__下一步。这是datetime对象(Python源)的实现方式__str__,它很容易实现,因为它已经具有以ISO格式显示它的功能:

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

设置__repr__ = __str__

这是对这里提出设置的另一个答案的批评__repr__ = __str__

设置__repr__ = __str__很愚蠢- __repr__是一个后备功能__str____repr__在编写a之前应先写一个供开发人员在调试中使用的a __str__

你需要一个__str__只有当你需要的对象的文本表示。

结论

__repr__为您编写的对象进行定义,以便您和其他开发人员在开发过程中使用它时可以得到一个可重现的示例。定义__str__何时需要其人类可读的字符串表示形式。

What is the difference between __str__ and __repr__ in Python?

__str__ (read as “dunder (double-underscore) string”) and __repr__ (read as “dunder-repper” (for “representation”)) are both special methods that return strings based on the state of the object.

__repr__ provides backup behavior if __str__ is missing.

So one should first write a __repr__ that allows you to reinstantiate an equivalent object from the string it returns e.g. using eval or by typing it in character-for-character in a Python shell.

At any time later, one can write a __str__ for a user-readable string representation of the instance, when one believes it to be necessary.

__str__

If you print an object, or pass it to format, str.format, or str, then if a __str__ method is defined, that method will be called, otherwise, __repr__ will be used.

__repr__

The __repr__ method is called by the builtin function repr and is what is echoed on your python shell when it evaluates an expression that returns an object.

Since it provides a backup for __str__, if you can only write one, start with __repr__

Here’s the builtin help on repr:

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

That is, for most objects, if you type in what is printed by repr, you should be able to create an equivalent object. But this is not the default implementation.

Default Implementation of __repr__

The default object __repr__ is (C Python source) something like:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

That means by default you’ll print the module the object is from, the class name, and the hexadecimal representation of its location in memory – for example:

<__main__.Foo object at 0x7f80665abdd0>

This information isn’t very useful, but there’s no way to derive how one might accurately create a canonical representation of any given instance, and it’s better than nothing, at least telling us how we might uniquely identify it in memory.

How can __repr__ be useful?

Let’s look at how useful it can be, using the Python shell and datetime objects. First we need to import the datetime module:

import datetime

If we call datetime.now in the shell, we’ll see everything we need to recreate an equivalent datetime object. This is created by the datetime __repr__:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

If we print a datetime object, we see a nice human readable (in fact, ISO) format. This is implemented by datetime’s __str__:

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

It is a simple matter to recreate the object we lost because we didn’t assign it to a variable by copying and pasting from the __repr__ output, and then printing it, and we get it in the same human readable output as the other object:

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

How do I implement them?

As you’re developing, you’ll want to be able to reproduce objects in the same state, if possible. This, for example, is how the datetime object defines __repr__ (Python source). It is fairly complex, because of all of the attributes needed to reproduce such an object:

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day,  # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s

If you want your object to have a more human readable representation, you can implement __str__ next. Here’s how the datetime object (Python source) implements __str__, which it easily does because it already has a function to display it in ISO format:

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

Set __repr__ = __str__?

This is a critique of another answer here that suggests setting __repr__ = __str__.

Setting __repr__ = __str__ is silly – __repr__ is a fallback for __str__ and a __repr__, written for developers usage in debugging, should be written before you write a __str__.

You need a __str__ only when you need a textual representation of the object.

Conclusion

Define __repr__ for objects you write so you and other developers have a reproducible example when using it as you develop. Define __str__ when you need a human readable string representation of it.


回答 6

在Hans Petter Langtangen 撰写的《用于计算科学Python脚本》一书的第358页中,明确指出:

  • 所述__repr__在所述物体的完整字符串表示目标;
  • __str__是返回一个字符串,不错的打印。

所以,我更喜欢将它们理解为

  • repr =复制
  • str =字符串(表示形式)

从用户的角度来看,尽管这是我在学习python时的一个误解。

在同一页面上还提供了一个很小但很好的示例,如下所示:

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'

On page 358 of the book Python scripting for computational science by Hans Petter Langtangen, it clearly states that

  • The __repr__ aims at a complete string representation of the object;
  • The __str__ is to return a nice string for printing.

So, I prefer to understand them as

  • repr = reproduce
  • str = string (representation)

from the user’s point of view although this is a misunderstanding I made when learning python.

A small but good example is also given on the same page as follows:

Example

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'

回答 7

除了给出的所有答案外,我想补充几点:

__repr__()当您在交互式python控制台上简单地写对象名称并按Enter时,将调用1)。

2)__str__()在带print语句的对象上使用时被调用。

3)如果__str__丢失,则打印并使用对象str()调用__repr__()进行任何功能。

4)__str__()容器,当被调用时将执行__repr__()其所包含元素的方法。

5)str()在内部调用__str__()可能会在没有基本情况的情况下递归,并且最大递归深度会出错。

6)__repr__()可以调用repr(),它将尝试自动避免无限递归,将表示的对象替换为...

Apart from all the answers given, I would like to add few points :-

1) __repr__() is invoked when you simply write object’s name on interactive python console and press enter.

2) __str__() is invoked when you use object with print statement.

3) In case, if __str__ is missing, then print and any function using str() invokes __repr__() of object.

4) __str__() of containers, when invoked will execute __repr__() method of its contained elements.

5) str() called within __str__() could potentially recurse without a base case, and error on maximum recursion depth.

6) __repr__() can call repr() which will attempt to avoid infinite recursion automatically, replacing an already represented object with ....


回答 8

老实说,eval(repr(obj))从未使用过。如果发现自己正在使用它,则应该停止操作,因为这样做eval很危险,而字符串是序列化对象(pickle替代使用)的效率很低的方法。

因此,我建议设置__repr__ = __str__。原因是str(list)调用repr元素(我认为这是Python 3未能解决的Python最大设计缺陷之一)。实际repr输出可能不会非常有用print [your, objects]

为了证明这一点,以我的经验,该repr函数最有用的用例是将一个字符串放入另一个字符串中(使用字符串格式)。这样,您不必担心转义引号或其他内容。但是请注意,这里没有eval发生任何事情。

In all honesty, eval(repr(obj)) is never used. If you find yourself using it, you should stop, because eval is dangerous, and strings are a very inefficient way to serialize your objects (use pickle instead).

Therefore, I would recommend setting __repr__ = __str__. The reason is that str(list) calls repr on the elements (I consider this to be one of the biggest design flaws of Python that was not addressed by Python 3). An actual repr will probably not be very helpful as the output of print [your, objects].

To qualify this, in my experience, the most useful use case of the repr function is to put a string inside another string (using string formatting). This way, you don’t have to worry about escaping quotes or anything. But note that there is no eval happening here.


回答 9

简而言之:

__str__用于显示对象的字符串表示形式,以方便他人阅读

__repr__用于显示的字符串表示对象。

假设我要创建一个Fraction类,其中分数的字符串表示形式为“(1/2)”,而对象(分数类)将表示为“分数(1,2)”

因此,我们可以创建一个简单的Fraction类:

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)

To put it simply:

__str__ is used in to show a string representation of your object to be read easily by others.

__repr__ is used to show a string representation of the object.

Let’s say I want to create a Fraction class where the string representation of a fraction is ‘(1/2)’ and the object (Fraction class) is to be represented as ‘Fraction (1,2)’

So we can create a simple Fraction class:

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)

回答 10

来自effbot 的(非官方)Python参考Wiki(归档副本)

__str__计算‘正规’的对象的字符串表示这不同于。__repr__在它不必须是一个有效的Python表达式:一个更方便或简洁表示可以被代替使用。

From an (An Unofficial) Python Reference Wiki (archive copy) by effbot:

__str__computes the “informal” string representation of an object. This differs from __repr__ in that it does not have to be a valid Python expression: a more convenient or concise representation may be used instead.


回答 11

str -从给定的对象创建一个新的字符串对象。

repr -返回对象的规范字符串表示形式。

区别:

str():

  • 使对象可读
  • 为最终用户生成输出

repr():

  • 需要复制对象的代码
  • 为开发人员生成输出

str – Creates a new string object from the given object.

repr – Returns the canonical string representation of the object.

The differences:

str():

  • makes object readable
  • generates output for end-user

repr():

  • needs code that reproduces object
  • generates output for developer

回答 12

其他答案中缺少的一个方面。的确,该模式通常是:

  • 目标__str__:人类可读
  • 目标__repr__:明确,可能通过机器读取eval

不幸的是,这种区别是有缺陷的,因为Python REPL和IPython都__repr__用于在REPL控制台中打印对象(请参阅PythonIPython的相关问题)。因此,以交互式控制台工作为目标的项目(例如Numpy或Pandas)已经开始忽略上述规则,__repr__而是提供了易于理解的实现方式。

One aspect that is missing in other answers. It’s true that in general the pattern is:

  • Goal of __str__: human-readable
  • Goal of __repr__: unambiguous, possibly machine-readable via eval

Unfortunately, this differentiation is flawed, because the Python REPL and also IPython use __repr__ for printing objects in a REPL console (see related questions for Python and IPython). Thus, projects which are targeted for interactive console work (e.g., Numpy or Pandas) have started to ignore above rules and provide a human-readable __repr__ implementation instead.


回答 13

摘自Fluent Python一书:

Python对象的基本要求是提供其自身的可用字符串表示形式,一种用于调试和记录,另一种用于呈现给最终用户。这就是为什么
特殊方法__repr____str__存在于数据模型中的原因。

From the book Fluent Python:

A basic requirement for a Python object is to provide usable string representations of itself, one used for debugging and logging, another for presentation to end users. That is why the
special methods __repr__ and __str__ exist in the data model.


回答 14

出色的答案已经涵盖了__str__和之间的区别__repr__,对我而言,这归结为前者甚至对于最终用户而言都是可读的,而后者对开发人员则尽可能有用。鉴于此,我发现的默认实现__repr__常常无法实现此目标,因为它忽略了对开发人员有用的信息。

出于这个原因,如果我有一个简单的方法__str__,我通常会尝试通过以下方法使两个方面都达到最佳:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))

Excellent answers already cover the difference between __str__ and __repr__, which for me boils down to the former being readable even by an end user, and the latter being as useful as possible to developers. Given that, I find that the default implementation of __repr__ often fails to achieve this goal because it omits information useful to developers.

For this reason, if I have a simple enough __str__, I generally just try to get the best of both worlds with something like:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))

回答 15

要记住的重要一件事是容器的__str__使用包含对象__repr__

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Python主张明确性胜于可读性__str__调用tuple调用包含的对象’ __repr__,即对象的“正式”表示形式。尽管正式表示比非正式表示更难读,但它对歧义没有任何歧义,并且更强大。

One important thing to keep in mind is that container’s __str__ uses contained objects’ __repr__.

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Python favors unambiguity over readability, the __str__ call of a tuple calls the contained objects’ __repr__, the “formal” representation of an object. Although the formal representation is harder to read than an informal one, it is unambiguous and more robust against bugs.


回答 16

简而言之:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'

In a nutshell:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'

回答 17

>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

原始数据print()的结果decimal.Decimal(23) / decimal.Decimal("1.05")被打印时被调用;此输出为字符串形式,可以使用来实现__str__()。如果仅输入表达式,我们将得到一个decimal.Decimal输出-该输出采用可通过表示的形式__repr__()。所有Python对象都有两种输出形式。字符串形式被设计为易于阅读。表示形式旨在产生输出,如果将其提供给Python解释器,则该输出将(如果可能)再现所表示的对象。

>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

When print() is called on the result of decimal.Decimal(23) / decimal.Decimal("1.05") the raw number is printed; this output is in string form which can be achieved with __str__(). If we simply enter the expression we get a decimal.Decimal output — this output is in representational form which can be achieved with __repr__(). All Python objects have two output forms. String form is designed to be human-readable. The representational form is designed to produce output that if fed to a Python interpreter would (when possible) reproduce the represented object.


回答 18

__str__可以通过调用在对象上调用,str(obj)并且应返回人类可读的字符串。

__repr__可以通过调用在对象上调用,repr(obj)并且应该返回内部对象(对象字段/属性)

此示例可能会有所帮助:

class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr

__str__ can be invoked on an object by calling str(obj) and should return a human readable string.

__repr__ can be invoked on an object by calling repr(obj) and should return internal object (object fields/attributes)

This example may help:

class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr

回答 19

理解__str____repr__直观,永久地将它们区分开。

__str__返回给定对象的字符串伪装体,以使眼睛可读
__repr__

在一个例子中看到它

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

至于 __repr__

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

我们可以__repr__方便地对结果进行算术运算。

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

如果将操作应用于 __str__

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

只返回错误。

另一个例子。

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

希望这可以帮助您建立具体的基础,以探索更多的答案。

Understand __str__ and __repr__ intuitively and permanently distinguish them at all.

__str__ return the string disguised body of a given object for readable of eyes
__repr__ return the real flesh body of a given object (return itself) for unambiguity to identify.

See it in an example

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

As to __repr__

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

We can do arithmetic operation on __repr__ results conveniently.

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

if apply the operation on __str__

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Returns nothing but error.

Another example.

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

Hope this help you build concrete grounds to explore more answers.


回答 20

  1. __str__必须返回字符串对象,而__repr__可以返回任何python表达式。
  2. 如果__str__缺少实现,则将__repr__功能用作备用。如果__repr__缺少函数实现,则没有回退。
  3. 如果__repr__函数返回对象的字符串表示形式,则可以跳过__str__函数的实现。

资料来源:https : //www.journaldev.com/22460/python-str-repr-functions

  1. __str__ must return string object whereas __repr__ can return any python expression.
  2. If __str__ implementation is missing then __repr__ function is used as fallback. There is no fallback if __repr__ function implementation is missing.
  3. If __repr__ function is returning String representation of the object, we can skip implementation of __str__ function.

Source: https://www.journaldev.com/22460/python-str-repr-functions


回答 21

__repr__用于除printstr方法(__str__定义a时!)之外的所有地方

__repr__ is used everywhere, except by print and str methods (when a __str__is defined !)