Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

display methods #13

Closed
14 tasks done
sglyon opened this issue Jul 13, 2014 · 12 comments
Closed
14 tasks done

display methods #13

sglyon opened this issue Jul 13, 2014 · 12 comments

Comments

@sglyon
Copy link
Member

sglyon commented Jul 13, 2014

Right now none of our classes print helpful messages when queried at the repl. Let's remedy this by implementing __str__, __repr__, and __unicode__ methods. The easiest thing would probably be to just implement __unicode__ and have the others just call and return its value:

def __str__(self):
    return unicode(self).encode('utf-8')

def __repr__(self):
    return unicode(self).encode('utf-8')

Here is a list of classes we need to update:

  • ARMA (arma.py)
  • AssetPrices (asset_pricing.py)
  • CareerWorkerProblem (career.py)
  • DiscreteRV (discrete_rv.py)
  • ECDF (ecdf.py)
  • ConsumerProblem (ifp.py)
  • JvWorker (jv.py)
  • Kalman (kalman.py)
  • LAE (lae.py)
  • LQ (lqcontrol.py)
  • LSS (lss.py)
  • SearchProblem (odu.py)
  • GrowthModel (optgrowth.py)
  • RBLQ (robustlq.py)
@albop
Copy link
Contributor

albop commented Jul 22, 2014

You don't need both since __str__ is calling __repr__ .
Also, your solution is not Python 3 compliant, since in Python 3 __str__ and __repr__ are supposed to return unicode strings, not encoded bytes.
Would there be any disadvantage in defining only __repr__ with regular strings ? (eg: def __repr__(self): return 'object description' . That would be interpreted as bytes in python 2 and as unicode in Python 3.

@davidrpugh
Copy link
Contributor

I agree with @albop. Defining only __repr__ with regular strings is the way to go.

@sglyon
Copy link
Member Author

sglyon commented Jul 22, 2014

Ok great, I'm glad we got updated suggestions. Thanks for the thoughts. If
anyone has any ideas as to what the specifics repr messages should be that
would be great to document here also.
On Jul 22, 2014 8:41 AM, "David R. Pugh" [email protected] wrote:

I agree with @albop https://github.com/albop. Defining only repr
with regular strings is the way to go.


Reply to this email directly or view it on GitHub
#13 (comment).

@sanguineturtle
Copy link
Contributor

In some of my work I use __repr__ to issue summary contextual information about the object. I like to add the basic parameter settings of a given model so that in IPython you can simply return on the object and it gives insight into the settings etc. I also like to add __class__ to the repr message to show which module the class lives in. Just some thoughts.

@albop
Copy link
Contributor

albop commented Jul 23, 2014

I've read a bit about these issues. Apparently __repr__ is used for machine readable code and __str__ for human readable (http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python).

In case there is no clear content to put in the __repr__ method, the more orthodox way would then be to code first __str__ instead of __repr__ (assuming we focus on human-readable string of course. __str__ is the one printed when you call print(obj).

There are other options for more detailed or more user friendly output : pretty-print strings and ipython representation for the display method. References are http://ipython.org/ipython-doc/2/api/generated/IPython.lib.pretty.html and http://ipython.org/ipython-doc/dev/api/generated/IPython.core.formatters.html . These are less important in the short tem. It would give a structure like:

class E:

    def __init__(self, gamma=2, eta=1):
        pass

     def __repr__(self):
         # machine parseable result:  eval(e.__repr__)  should return e (if possible)
         return "E(gamma=2, eta=1)"

    def __str__(self):
        # Human friendly text
         return 'Model\n  gamma = 2\n  eta=1'

    def _repr_pretty_(self,p,cycle):
        # Pretty print representation  
        p.text("Model E\n  gamma = 2\n  eta=1")

    def _repr_html_(self):
         # nice html representation for the notebook
         return "<b>Model</b></p>gamma = 2</p>eta=1"

@sglyon
Copy link
Member Author

sglyon commented Jan 28, 2015

I would like like to revisit this and potentially implement it in the next few days.

I wanted to ping this issue to give people a chance to comment on what they would like to see in these.

I like what @albop presented in the previous comment.

We might try something like this (for starters, this is really just to get a conversation going):

    def __str__(self):
        m = "GrowthModel:\n"
        m += "  - beta (discount factor): %.3f\n" % self.beta
        m += "  - u (utility function): %s\n" % self.u.__str__()
        m += "  - f (production function): %s\n" % self.f.__str__()
        m += "  - grid: np.linspace(1e-6, %.2f, %i)\n" % (self.grid.max(),
                                                          self.grid.size)
        return m

    def __repr__(self):
       m = "GrowthModel(beta=%.3f, grid_max=%.3f, grid_size=%i)"
       return m % (self.beta, self.grid.max(), self.grid.size)

which produces the following:

In [1]: from quantecon.models import GrowthModel

In [2]: g = GrowthModel()

In [3]: g
Out[3]: GrowthModel(beta=0.950, grid_max=2.000, grid_size=150)

In [4]: print(g)
GrowthModel:
  - beta (discount factor): 0.950
  - u (utility function): <ufunc 'log'>
  - f (production function): <function <lambda> at 0x106b7a410>
  - grid: np.linspace(1e-6, 2.00, 150)

These are definitely not the only possibilities, but I just wanted to throw them out there as examples of two having a very descriptive __str__ method and a __repr__ method that can be copied and pasted and create a new GrowthModel instance. I would love it if the __repr__ for the classes would produce a string containing the code needed to reproduce the object, but when we have functions as parameters I don't know how this is possible.

We could also add other things like Model Name (Author, Year): on the first line to add a standard reference in the __str__ methods.

Does anyone have any suggestions?

@jstac
Copy link
Contributor

jstac commented Jan 28, 2015

This would be great to have done. I don't have any concrete views on how. I guess I would be in favor of keeping it fairly simple. For things like the growth model it might be sensible to print out a link to the relevant page on quant-econ.net --- but I don't want push this idea too hard because I know we want to decouple library and website. Feel free to ignore.

@sglyon
Copy link
Member Author

sglyon commented Jan 28, 2015

That's a good idea. I'm in favor of it as I see the modes more as serving more of a pedagogical purpose than as standalone tools.

What did you think about the sketch outlined above?

@jstac
Copy link
Contributor

jstac commented Jan 28, 2015

Looks great.

@mmcky
Copy link
Contributor

mmcky commented Jan 29, 2015

@spencerlyon2 I think your suggestion is excellent. I have used __repr__ for trade classes to present some basic stats (importers, exporters etc) about the object - and it has been really helpful.

Is there a way we could use sympy to represent the functions?

@sglyon
Copy link
Member Author

sglyon commented Jan 29, 2015

I hadn't thought of sympy.

I was thinking about trying to use inspect.getsource, but I am worried about the robustness of it.

@sglyon
Copy link
Member Author

sglyon commented Jan 29, 2015

Closing in favor of #114

@sglyon sglyon closed this as completed Jan 29, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants