This answer mentions that either
fig = plt.figure()
fig.patch.set_facecolor('black')
or
plt.rcParams['figure.facecolor'] = 'black'
will change the value in the rcParams dictionary for the key 'figure.facecolor'.
Suppose that my script has made several changes to the values in a nondeterministic way based on user interaction, and I want to undo all of that and go back to matplotlib's default parameters and behavior.
In the beginning of the script I could check matplotlib.rcParams and store either the whole dictionary, or values for certain keys, and then restore them one at a time or with the .update() method, but I don't know if that's wise because I don't know how else the matplotlib.RcParams instance is used (it's not just a dictionary). It does have a .setdefault() method but I can't understand what help returns on that:
Help on method setdefault in module collections.abc:
setdefault(key, default=None) method of matplotlib.RcParams instance
D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
Is there some kind of restore the original default values feature, or should I just wing-it by updating the whole thing with the copy that I've stored?
Per my understanding and answers to How to recover matplotlib defaults after setting stylesheet you should be able to do this:
import matplotlib
matplotlib.rcParams.update(matplotlib.rcParamsDefault)
You could also check the site-packages/matplotlib/mpl-data folder for the file named matplotlibrc. It should have the entire default values there.
Related
As Zen of Python says:
There should be one– and preferably only one –obvious way to do it.
I can't decide which one of the following lines is better:
ps.cfg is a python dict
if cfg.get("runner") is None:
if "runner" not in cfg:
Is one of them obviously better, or could we say that they are both OK?
It depends on what you want to achieve. If you want to make sure that an element at a certain key exists in that dictionary, i.e. something was inserted at that key, you should utilize capabilities that tell you exactly that. Like in your case:
if "runner" not in cfg:
If you really don't care if actually an element at a certain key exists in that dictionary and you just want to see if trying to retrieve an element of the dictionary will give you None as result, you can also work with the None check.
Just consider that by calling get('some_key') and checking the returned value against None this won't tell you if there is an element existing at key some_key. Because no one prevents you from inserting an element without a value (meaning the value None) into a dictionary at that very key.
I have discovered the pandas DataFrame.query method and it almost does exactly what I needed it to (and implemented my own parser for, since I hadn't realized it existed but really I should be using the standard method).
I would like my users to be able to specify the query in a configuration file. The syntax seems intuitive enough that I can expect my non-programmer (but engineer) users to figure it out.
There's just one thing missing: a way to select everything in the dataframe. Sometimes what my users want to use is every row, so they would put 'All' or something into that configuration option. In fact, that will be the default option.
I tried df.query('True') but that raised a KeyError. I tried df.query('1') but that returned the row with index 1. The empty string raised a ValueError.
The only things I can think of are 1) put an if clause every time I need to do this type of query (probably 3 or 4 times in the code) or 2) subclass DataFrame and either reimplement query, or add a query_with_all method:
import pandas as pd
class MyDataFrame(pd.DataFrame):
def query_with_all(self, query_string):
if query_string.lower() == 'all':
return self
else:
return self.query(query_string)
And then use my own class every time instead of the pandas one. Is this the only way to do this?
Keep things simple, and use a function:
def query_with_all(data_frame, query_string):
if query_string == "all":
return data_frame
return data_frame.query(query_string)
Whenever you need to use this type of query, just call the function with the data frame and the query string. There's no need to use any extra if statements or subclass pd.Dataframe.
If you're restricted to using df.query, you can use a global variable
ALL = slice(None)
df.query('#ALL', engine='python')
If you're not allowed to use global variables, and if your DataFrame isn't MultiIndexed, you can use
df.query('tuple()')
All of these will property handle NaN values.
df.query('ilevel_0 in ilevel_0') will always return the full dataframe, also when the index contains NaN values or even when the dataframe is completely empty.
In you particular case you could then define a global variable all_true = 'ilevel_0 in ilevel_0' (as suggested in the comments by Zero) so that your engineers could use the name of the global variable in their config file instead.
This statement is just a dirty way to properly query True like you already tried. ilevel_0 is a more formal way of making sure you are referring the index. See the docs here for more details on using in and ilevel_0: https://pandas.pydata.org/pandas-docs/stable/indexing.html#the-query-method
Many lines and points possible that I would like to be able to track when I line/point has been moused over. Is there any short codeable way of doing it or do I half to come up with hundreds/thousands of different element names.
I've tried
self.z[0].canvas.create_line()
self.z[1].canvas.create_line()
as well as
self.z(0).canvas.create_line()
self.z(1).canvas.create_line()
to only get back an error saying something like z can't be an integer, aka you can't do that stupid:)
Is there anyway to set up a nice for loop and create the lines/points and then be able to test test them once they are created. I can test the points the way I want to be able to test them but I would just like an easier way of creating the lines/points.
Worst case scenario is there a way of setting up something like
self.z1.canvas
self.z2.canvas
self.z3.canvas
but have 1,2,3 each be able to be increased through a for loop? I'm not sure if I have ever seen something like what I'm suggesting be made mention of or not.
Every time you create an item on a canvas, it returns a unique id. You can store that id in a list.
self.lines = []
for x in range(1000):
item = self.canvas.create_line(...)
self.lines.append(item)
That being said, you don't need to keep any of these in an array to " track when I line/point has been moused over.". You can set up bindings for that.
I know how to sort lines in Sublime (ctrl+p "sort"). The problem is it doesn't sort some characters as I want, namely åäö.
Is there some way to change how sublime orders the text? Perhaps by a specific locale? It would also be interesting to be able to sort V and W as being equal.
Example: I want the following words to be sorted in this order:
bår
bär
bör
but Sublime sorts it like this:
bär
bår
bör
There has been a similar request logged on ST's issue tracker: https://github.com/SublimeTextIssues/Core/issues/1324
One of the ST developers replied:
Sorting in Python 3 uses Unicode code points as the basis for sorting. Sublime Text doesn't know what language your encoding represents, so it doesn't use locale-based sorting rules.
This seems like it is probably best solved by a package dedicated to providing locale-based collation rules.
Using https://packagecontrol.io/packages/PackageResourceViewer, we can see that the case_sensitive_sort method in Packages/Default/sort.py uses Python's built in list.sort method. Typing the following into ST's Python console (View menu -> Show Console), we get the same result as you have shown:
>>> a = ['bår', 'bär', 'bör']
>>> a.sort()
>>> a
['bär', 'bår', 'bör']
So the answer is that there is no setting to configure the sorting behavior, and nor is there likely to be in future. However, according to https://docs.python.org/3/howto/sorting.html#odd-and-ends, it is possible to use a locale-aware sort using locale.strxfrm as a key function.
Let's try. On Windows, I had to use
>>> import locale
>>> locale.setlocale(locale.LC_COLLATE, 'sve')
'Swedish_Sweden.1252'
to get Python to use a Swedish locale - as per https://stackoverflow.com/a/956084/4473405
>>> a.sort(key=locale.strxfrm)
>>> a
['bår', 'bär', 'bör']
Using this knowledge, you might choose to change the case_sensitive_sort method, so that ST's built in sort functionality (Edit menu -> Sort Lines (Case Sensitive)) will use the locale aware sort key. Note that saving the sort.py file opened from PackageResourceViewer will create an override, so that if future builds of ST include changes to sort.py, you won't see them until you delete the override (which you can do by finding the file using the Preferences menu -> Browse Packages -> Default. You can reapply your changes afterwards, if appropriate, using the exact same steps.)
You can also change the case_insensitive_sort method from
txt.sort(key=lambda x: x.lower())
to
txt.sort(key=lambda x: locale.strxfrm(x.lower()))
Note that, if your correct locale isn't picked up automatically (it probably defaults to C), then setting the locale in this (case_sensitive_sort) method isn't recommended, even if, immediately afterwards, you restore it back to what it was beforehand - so use at your own risk.
It is generally a bad idea to call setlocale() in some library routine, since as a side effect it affects the entire program. Saving and restoring it is almost as bad: it is expensive and affects other threads that happen to run before the settings have been restored.
You could instead add the following to the end of the sort.py file:
def plugin_loaded():
import locale
locale.setlocale(locale.LC_COLLATE, '')
which will, when the plugin is loaded, allow Python to infer the locale from your LANG env var, as per https://docs.python.org/3/library/locale.html#locale.setlocale. The advantage being you only set it once, and hopefully won't introduce any problems with other plugin code executing at the same time.
Happy sorting!
Technical background: Python 3.4 + PyGame 1.9.2 on a Win XP system.
IMPORTANT
The original title was misleading as it turned out that is has NOTHING to do with how Python dictionaries work! It was just a coincidence it happened with a dictionary. I quickly explain the problem, hoping it will be useful to somebody in the future.
There are two dictionaries representing the two players' "boards" (it's kind of a battleship/sea battle as computer game) containing position-tuples (x, y) as keys and surfaces as keys' content. Some Pseudo-Code for clarification:
surface1 = pygame.Surface((w, h)).convert()
surface1.fill(WATER_COLOUR)
dict1 = {(x1, y1): surface1.copy(), (x2, y2): surface1.copy(), (x3, y3): surface1.copy()}
dict2 = dict1.copy()
In the course of the game the players would click on the display and if they'd hit a valid game field, that field would change its colour depending on whether a ship has been hit or not.
def clicked(mousepos, key):
if active_player == 1:
if mousepos_inside_enemy_ship_rectangle(mousepos):
dict1[position_of_mouse].fill((255, 0, 0)) # Make it red
else:
dict1[position_of_mouse].fill((0, 0, 0)) # Make it black
To my surprise ALL the square-surfaces would change their colour in both dictionaries! I first thought, it's a problem with the dictionary, until I found out, that it's a problem with how surfaces work in PyGame.
It seems that all surface1.copy() refer to one single copy of surface1. So to say: if I change one of the copies, all the others look the same, they do not really copy it, they just reference it!
Two solutions there are:
Create a surface for each state: one for "not clicked yet", one for "clicked but missed" and one for "clicked and hit". Then change the dictionaries key to the respective surface.
Create an individual surface for each key in the dictionary and then fill them with the respective colours individually. That also works.
Thanks to everybody who tried to resolve it and sorry for the trouble... It's a completely different problem. I updated the title and the keywords, hoping it helps somebody else in the future. I left the old question text for reference. And whoever added the link to that other dictionary question: Please remove it, it's not about dictionaries but surfaces, thanks!
Pat
OLD QUESTION TEXT Left for reference
My script has a function f() returning a dictionary:
def f(data):
d = {}
for n in range(len(data)):
d.update({n: data[n]})
return d
I need two dictionaries starting with the precisely same data, so I can modify these data in different ways.
dict1 = f(data)
dict2 = dict1.copy()
To my surprise, when I modify dict1 the same changes are also shown by dict2! I thought the copy would be independent from the original - have I misunderstood something?
It has definitely something to do with the .copy() method. When I change my code like this:
dict1 = f(data)
dict2 = f(data)
I receive precisely what I wanted and I can modify both dictionaries differently without interfering with each other.
Basically this solves my problem but it raises a number of questions... Have I misunderstood what .copy() does? Is this a general issue in this Python version?
//edit:
To clarify what I mean by "modify":
Some of the keys' data in dict1 is changed, if the keys meet a certain condition:
for key in dict1:
if key == meets_this_condition:
dict1[key] = new_data
In another method I constantly compare the contents of the two dictionaries and call certain functions depending on them either being the same or being different
for key in dict1:
if dict1[key] == dict2[key]:
do_something()
else:
do_something_else()
Thanks for any insights!
Pat
I would try use deepcopy function something like
dict2=copy.deepcopy(dict1);
import the copy library
as I remember .copy make a shallow copy so it only copy pointers. so if you modified one in some cases the copy also would be change.