Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Lazy initialization of axis default tick list #9727

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

Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
lazy initialization of axis default tick list
  • Loading branch information
timhoffm committed Nov 12, 2017
commit 0cc96fcc80b76d34809153dcf32491b87a6fc4d7
53 changes: 45 additions & 8 deletions 53 lib/matplotlib/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import matplotlib.units as munits
import numpy as np
import warnings
import itertools

GRIDLINE_INTERPOLATION_STEPS = 180

Expand Down Expand Up @@ -625,6 +626,42 @@ class Ticker(object):
formatter = None


class _LazyDefaultTickList(object):
"""
A lazy evaluating placeholder for the default tick list.

On access the class replaces itself with the default 1-element list. We
use the lazy evaluation so that :meth:`matplotlib.axis.Axis.reset_ticks`
can be called multiple times without the overhead of initialzing every
time.

https://github.com/matplotlib/matplotlib/issues/6664
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to consider that checking the git blame is sufficient to see where this comes from, and prefer not adding explicit links to issues (otherwise it's a bit endless). Not a huge deal of course.

"""
def __init__(self, axis, major=True):
self.axis = axis
self.major = major

def _instantiate_list(self):
if self.major:
self.axis.majorTicks = [self.axis._get_tick(major=True)]
self.axis._lastNumMajorTicks = 1
return self.axis.majorTicks
else:
self.axis.minorTicks = [self.axis._get_tick(major=False)]
self.axis._lastNumMinorTicks = 1
return self.axis.minorTicks

def __iter__(self):
return iter(self._instantiate_list())

def __len__(self):
return len(self._instantiate_list())

def __getitem__(self, key):
l = self._instantiate_list()
return l[key]


class Axis(artist.Artist):
"""
Public attributes
Expand Down Expand Up @@ -781,13 +818,12 @@ def reset_ticks(self):
# build a few default ticks; grow as necessary later; only
# define 1 so properties set on ticks will be copied as they
# grow
del self.majorTicks[:]
del self.minorTicks[:]

self.majorTicks.extend([self._get_tick(major=True)])
self.minorTicks.extend([self._get_tick(major=False)])
self._lastNumMajorTicks = 1
self._lastNumMinorTicks = 1
if not isinstance(self.majorTicks, _LazyDefaultTickList):
del self.majorTicks[:]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need this any more since the list is being removed, no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guess you're right. I was wondering anyway, why the previous code bothered to del every item from the list and not just created a new list (self.majorTicks=[] would have been my expectation in the original code).

Also, can you tell if there's still a need for self._lastNumMajorTicks? I haven't looked into this so far. It feels like a helper state, that might not be necessary. If you don't know right now, I can check myself.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it worked this way so that any use of self.majorTicks would point to the same list. It's interesting that all the tests still pass though, as clearly this new class does not make that same guarantee.

self.majorTicks = _LazyDefaultTickList(self, major=True)
if not isinstance(self.minorTicks, _LazyDefaultTickList):
del self.minorTicks[:]
self.minorTicks = _LazyDefaultTickList(self, major=False)

def set_tick_params(self, which='major', reset=False, **kw):
"""
Expand Down Expand Up @@ -872,7 +908,8 @@ def _translate_tick_kw(kw, to_init_kw=True):

def set_clip_path(self, clippath, transform=None):
artist.Artist.set_clip_path(self, clippath, transform)
for child in self.majorTicks + self.minorTicks:
for child in itertools.chain(iter(self.majorTicks),
iter(self.minorTicks)):
child.set_clip_path(clippath, transform)
self.stale = True

Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.