I have a class that wraps around python deque from collections. When I go and create a deque x=deque(), I create a empty deque object. So if I fill it up: x.append(0) and simply type in x on the console, i get:
In[78]: x
Out[78]: deque([0])
My question is how can I output the same thing as above when I have a wrapper for class deque. For example.
class deque_wrapper:
def __init__(self):
self.data_structure = deque()
def newCustomAddon(x):
return len(self.data_structure)
Ie
In[74]: x = deque_wrapper()
In[75]: x
Out[75]: <__main__.deque_wrapperat 0x7e3d0f0>
I want to customize what gets printed out as oppose to just a memory location. What can I do?
I want to customize what gets printed out as oppose to just a memory location. What can I do?
This is exactly what __repr__ is for:
Called by the repr() built-in function to compute the “official” string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment). If this is not possible, a string of the form <...some useful description...> should be returned.
Because you didn't define a __repr__, you're getting the default implementation from object (assuming Python 3… otherwise, you've written a classic class, which is a bad idea, and you don't want to learn how they get their defaults when you can just stop using them…), which just returns that string with the object's type name and address.
Note the __str__ method below __repr__ in the docs. If the most human-readable representation and the valid-Python-expression representation are not the same, define both methods. Otherwise, just define __repr__, and __str__ will use it by default.
So, if you want to print the exact same thing as deque, just delegate __repr__:
def __repr__(self):
return repr(self.data_structure)
If you want to wrap it in something:
def __repr__(self):
return '{}({!r})'.format(type(self).__name__, self.data_structure)
Note that I didn't call repr in the second version, because that's exactly what !r means in a format string. But really, in this case, you don't need either; a deque has the same str and repr.
Delegate the generation of the representation.
class deque_wrapper:
...
def __repr__(self):
return repr(self.data_structure)
Related
I am writing a custom class which extends the default python lists by adding some new functions such as shuffling , adding, multiplying etc.
The code goes something like this:
class xlist(list):
def __init__(self, original_list: list):
self._olist = original_list
def sumall(self) -> int:
sum = 0
for e in self._olist:
sum += e
return sum
...
But while doing some calculations I needed to get the type of a instance of a xlist. I want to do something like this :
>>> from xlist import xlist
>>> x = xlist([1, 2, 3])
>>> type(x)
When I do this I get <class 'xlist.xlist'> , but I want it to return list.
I am little confused about Metaclasses which seems to be able to solve the problem.
Any Help?
Why do you expect type(x) to return list if you're really creating an xlist? Your xlist inherits from list, so every xlist object is an instance of a list since it inherits from it all of its behaviour (and extends by adding some new functionality).
Note that:
x = xlist([1, 2, 3])
isinstance(x, list)
returns True. You might also want to have a look at Difference between type() and isinstance()
There are two ways for Python to check the class of an object - one is calling type and the other is checking the __class__ slot.
Most times both return the samething, but one can modify the class (for example, by customizing attribute access on the metaclass) so that __class__ will "lie" and Python code using myobject.__class__ will get the "false" information.
However, underneath, the "true" __class__ slot in the type object will always hold a reference to the real type - and this can't be falsified. Any C extension, and maybe even a few Python extensions, and the return to type(myobject) itself will see the real class.
Changing the contents of this slot actually changes the class of your instance. It is feasible from pure Python with a simple = attribution - but there are guards in place on this assignment to ensure it is only done across types that have a compatible memory layout. Forcing it to change to an incompatible type (Via an extension, or ctypes) will get your Python runtime to segfault.
All that said, there is no reason to lie about your class to users of your class -they should be able to "see" that the object the are holding is a xlist and not a list, and that xlists are also list objects, due to inheritance. Falsifying this information would be a rather bad practice. On the other hand, there are few calls, in Python stdlib itself, that require the underlying object to really be a list and won't accept subtypes (notoriously Python´s json.dumps serialization). That call has a native code path and won't be fooled by customizing access to __class__. However, the same call also has a Python only codepath that is triggered by setting some of the optional arguments (for example, by passing ident=4 on the call). If that is you are trying to achieve (fool some code that requires an strict list) you have to heck that, and if it is Python code, it is doable. In the specific case of json.dump, you'd be better monkeypatching the encoder to use a less strict check than to falsify your object - because I think the code there uses type for the checing.
So, with all of the above said, the "metaclass trick" to Falsify the return of .__class__ can be as simple as:
class xlist(list, metaclass=Meta):
def __init__(self, original_list: list):
self._olist = original_list
def sumall(self) -> int:
sum = 0
for e in self._olist:
sum += e
return sum
#property
def __class__(self):
return list
Say I want to debug a simple class with an attribute myattribute. I create a repr method like this:
class SimpleClass:
def __repr__(self):
return "{0.myattribute}".format(self)
It feels a bit redundant, so I would prefer to use format directly:
class SimpleClass:
__repr__ = "{0.myattribute}".format
...but that fails with an IndexError: tuple index out of range. I understand it that format cannot access the self argument, but I do not see why.
Am I doing something wrong, is this a CPython limitation – or what else?
"{0.myattribute}".format is already a bound method on the string object ("{0.myattribute}"). So when the calling code attempts to look up, say, x.__repr__ (where x is a SimpleClass instance), Python finds the __repr__ attribute of SimpleClass, but then cannot recognize it as a SimpleClass method - the descriptor protocol is not honoured (the string method has no __get__ attribute).
It appears that in 3.4, using a lambda will work, although I could have sworn it had to be a real function in previous versions. functools.partial will not work. But you really should be using a real function anyway. Sorry it's not as DRY as you'd like.
Just encountered an example Fraction class and am not too sure what the difference between these two methods is. Once __str__ has been implemented doesn't show become redundent ?
def __str__(self):
return str(self.num)+"/"+str(self.den)
def show(self):
print(self.num,"/",self.den)
I realise __str__ is a magic method who's implementation takes care of any context that requires a string version of the class. Just can't see the point of the show(self) method ?
EDIT
Is show a generic method that most classes require?
My problem is if I have a fraction x then all I need do is print(x) and I will see 1\2 or what ever the instance holds - so why would one ever bother implementing an additional method show ?
The purpose of having a __str__ method is to create a string representation of the object. __str__ should return a string. If the implementation of __str__ instead printed the string representation and returned nothing, when the object was used in a string context a TypeError will be raised. Take for example:
def __str__(self):
print '%f/%f'%(self.num,self.den)
If we went to display a fraction object like so:
f = Fraction(1,2)
print f
we get an exception:
Traceback (most recent call last):
File "/Users/.../Desktop/...", line 13, in <module>
print f
TypeError: __str__ returned non-string (type NoneType)
>>>
This is because __str__ is used to get the string representation of the object, not print it (by convention that is, you could print as long as you return a string). That's what the print statment/function is used for in conjunction with a __str__ method.
On the other hand a method like show:
def show(self):
print(self.num,"/",self.den) #or even print(self) (for the last part of answer)
Is essentially equivalent to print(f) in the above case (except it includes spaces next to the operands). show is used to output the string representation, while __str__ to get the representation.
However, additional logic may be added to show which isn't appropriate/necessary when constructing a string representation, and hence make sense to have both methods.
You can however use a method like show where a print statement is inappropriate i.e:
if f.show(): pass
if print(f): pass #raise exception
The __str__ method is being very careful to make sure everything is a str and so it returns a str.
The show method is relying on print to convert self.num and self.den to str implicitly. It displays the result as a side-effect, and returns None
print will insert a space between each parameter.
>>> str(3)+"/"+str(5)
'3/5'
>>> print(3,"/",5)
3 / 5
If you don't care about the extra spaces, there's really no reason not to use
def show(self):
print(self)
perhaps the author thinks it's clearer not to do it that way.
Decoupling show and __str__ this way may also be surprising when you try to make a subclass. If the subclass overrides __str__, you would probably expect the change to be reflected in show too.
__str__ is a magic method that will be called each time object will be treated as string, for example str(fraction_instance)
I have a python object that conceptually allows access to an array full of strings through iterators and getters. However, since calculating the exact value of each element in the array is really expensive, I am looking into returning a proxy object for the content of each slot in the array and then calculate on the fly the actual value when it is really needed.
Namely, I would like to write this:
bar = foo.get(10) # just returns a proxy
baz = bar # increase proxy reference
l = [baz] # actually increase proxy reference again.
print baz # ooh, actually need the value. Calculate it only the fly.
v = '%s' % bar # I need the value here again
if bar is None: # I need the value here again
print 'x'
if bar: # I need the value here again
print 'x'
for i in bar: # I need the value here again
print i
In C++, I would try to overload the dereferencing operator... Any idea ?
I understand that for each of these cases, I could overload specific python 'magic' functions (such as __str__ for print baz) but I wonder if:
this is going to actually cover all possible usecases (are there ways to access the content of a variable that does not involve using a python magic function)
there is a more generic way to do this
In python you'd return a custom type, and override the __str__() method to calculate the string representation at printing time.
class MyCustomType(object):
def __str__(self):
return "My string is really costly to produce"
Depending on your use-cases, you are still looking at the various hooks python provides:
Attribute access on custom classes can be hooked into with the __getattr__ method, or by using a property.
Accessing individual items in a sequence-like class (list, tuple, string) and mapping-type classes can be hooked into with __getitem__.
You'll have to decide, based on your use-case, what you need to hook into, at which point it becomes inevitable that you need to make the expensive calculation. Python will let you hook that almost any point in an object's lifetime with ease.
I was looking at the builtin object methods in the Python documentation, and I was interested in the documentation for object.__repr__(self). Here's what it says:
Called by the repr() built-in function
and by string conversions (reverse
quotes) to compute the “official”
string representation of an object. If
at all possible, this should look like
a valid Python expression that could
be used to recreate an object with the
same value (given an appropriate
environment). If this is not possible,
a string of the form <...some useful
description...> should be returned.
The return value must be a string
object. If a class defines repr()
but not str(), then repr() is
also used when an “informal” string
representation of instances of that
class is required.
This is typically used for debugging,
so it is important that the
representation is information-rich and
unambiguous
The most interesting part to me, was...
If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value
... but I'm not sure exactly what this means. It says it should look like an expression which can be used to recreate the object, but does that mean it should just be an example of the sort of expression you could use, or should it be an actual expression, that can be executed (eval etc..) to recreate the object? Or... should it be just a rehasing of the actual expression which was used, for pure information purposes?
In general I'm a bit confused as to exactly what I should be putting here.
>>> from datetime import date
>>>
>>> repr(date.today()) # calls date.today().__repr__()
'datetime.date(2009, 1, 16)'
>>> eval(_) # _ is the output of the last command
datetime.date(2009, 1, 16)
The output is a string that can be parsed by the python interpreter and results in an equal object.
If that's not possible, it should return a string in the form of <...some useful description...>.
It should be a Python expression that, when eval'd, creates an object with the exact same properties as this one. For example, if you have a Fraction class that contains two integers, a numerator and denominator, your __repr__() method would look like this:
# in the definition of Fraction class
def __repr__(self):
return "Fraction(%d, %d)" % (self.numerator, self.denominator)
Assuming that the constructor takes those two values.
Guideline: If you can succinctly provide an exact representation, format it as a Python expression (which implies that it can be both eval'd and copied directly into source code, in the right context). If providing an inexact representation, use <...> format.
There are many possible representations for any value, but the one that's most interesting for Python programmers is an expression that recreates the value. Remember that those who understand Python are the target audience—and that's also why inexact representations should include relevant context. Even the default <XXX object at 0xNNN>, while almost entirely useless, still provides type, id() (to distinguish different objects), and indication that no better representation is available.
"but does that mean it should just be an example of the sort of expression you could use, or should it be an actual expression, that can be executed (eval etc..) to recreate the object? Or... should it be just a rehasing of the actual expression which was used, for pure information purposes?"
Wow, that's a lot of hand-wringing.
An "an example of the sort of expression you could use" would not be a representation of a specific object. That can't be useful or meaningful.
What is the difference between "an actual expression, that can ... recreate the object" and "a rehasing of the actual expression which was used [to create the object]"? Both are an expression that creates the object. There's no practical distinction between these. A repr call could produce either a new expression or the original expression. In many cases, they're the same.
Note that this isn't always possible, practical or desirable.
In some cases, you'll notice that repr() presents a string which is clearly not an expression of any kind. The default repr() for any class you define isn't useful as an expression.
In some cases, you might have mutual (or circular) references between objects. The repr() of that tangled hierarchy can't make sense.
In many cases, an object is built incrementally via a parser. For example, from XML or JSON or something. What would the repr be? The original XML or JSON? Clearly not, since they're not Python. It could be some Python expression that generated the XML. However, for a gigantic XML document, it might not be possible to write a single Python expression that was the functional equivalent of parsing XML.
'repr' means representation.
First, we create an instance of class coordinate.
x = Coordinate(3, 4)
Then if we input x into console, the output is
<__main__.Coordinate at 0x7fcd40ab27b8>
If you use repr():
>>> repr(x)
Coordinate(3, 4)
the output is as same as 'Coordinate(3, 4)', except it is a string. You can use it to recreate a instance of coordinate.
In conclusion, repr() method is print out a string, which is the representation of the object.
To see how the repr works within a class, run the following code, first with and then without the repr method.
class Coordinate (object):
def __init__(self,x,y):
self.x = x
self.y = y
def getX(self):
# Getter method for a Coordinate object's x coordinate.
# Getter methods are better practice than just accessing an attribute directly
return self.x
def getY(self):
# Getter method for a Coordinate object's y coordinate
return self.y
def __repr__(self): #remove this and the next line and re-run
return 'Coordinate(' + str(self.getX()) + ',' + str(self.getY()) + ')'
>>>c = Coordinate(2,-8)
>>>print(c)
I think the confusion over here roots from the english. I mean __repr__(); short for 'representation' of the value I'm guessing, like #S.Lott said
"What is the difference between "an actual expression, that can ... recreate the object" and "a rehasing of the actual expression which was used [to create the object]"? Both are an expression that creates the object. There's no practical distinction between these. A repr call could produce either a new expression or the original expression. In many cases, they're the same."
But in some cases they might be different. E.g; coordinate points, you might want c.coordinate to return: 3,5 but c.__repr__ to return Coordinate(3, 5). Hope that makes more sense...