2019年5月17日 星期五

[Git 文章收集] How to reset, revert, and return to previous states in Git

Source From Here 
Preface 
One of the lesser understood (and appreciated) aspects of working with Git is how easy it is to get back to where you were before—that is, how easy it is to undo even major changes in a repository. In this article, we'll take a quick look at how to reset, revert, and completely return to previous states, all with the simplicity and elegance of individual Git commands. 

Reset 
Let's start with the Git command reset. Practically, you can think of it as a "rollback"—it points your local environment back to a previous commit. By "local environment," we mean your local repository, staging area, and working directory. Take a look at Figure 1. Here we have a representation of a series of commits in Git. A branch in Git is simply a named, movable pointer to a specific commit. In this case, our branch master is a pointer to the latest commit in the chain. 

Fig. 1: Local Git environment with repository, staging area, and working directory 

If we look at what's in our master branch now, we can see the chain of commits made so far: 
$ git log --oneline
b764644 File with three lines
7c709f0 File with two lines
9ef9173 File with one line

What happens if we want to roll back to a previous commit. Simple—we can just move the branch pointer. Git supplies the reset command to do this for us. For example, if we want to reset master to point to the commit two back from the current commit, we could use either of the following methods: 
$ git reset 9ef9173 # using an absolute commit SHA1 value 9ef9173

Or 
$ git reset current~2 # using a relative value -2 before the "current" tag

Figure 2 shows the results of this operation. After this, if we execute a git log command on the current branch (master), we'll see just the one commit. 
$ git log --oneline
9ef9173 File with one line


Fig. 2: After reset 

The git reset command also includes options to update the other parts of your local environment with the contents of the commit where you end up. These options include: hard to reset the commit being pointed to in the repository, populate the working directory with the contents of the commit, and reset the staging areasoft to only reset the pointer in the repository; and mixed (the default) to reset the pointer and the staging area. 

Using these options can be useful in targeted circumstances such as git reset --hard This overwrites any local changes you haven't committed. In effect, it resets (clears out) the staging area and overwrites content in the working directory with the content from the commit you reset to. Before you use the hard option, be sure that's what you really want to do, since the command overwrites any uncommitted changes. 

Revert 
The net effect of the git revert command is similar to reset, but its approach is different. Where the reset command moves the branch pointer back in the chain (typically) to "undo" changes, the revert command adds a new commit at the end of the chain to "cancel" changes. The effect is most easily seen by looking at Figure 1 again. If we add a line to a file in each commit in the chain, one way to get back to the version with only two lines is to reset to that commit, i.e., git reset HEAD~1

Another way to end up with the two-line version is to add a new commit that has the third line removed—effectively canceling out that change. This can be done with a git revert command, such as: 
$ git revert HEAD

Because this adds a new commit, Git will prompt for the commit message: 
  1. Revert "File with three lines"  
  2.   
  3. This reverts commit b764644bad524b804577684bf74e7bca3117f554.  
  4.   
  5. # Please enter the commit message for your changes. Lines starting  
  6. # with '#' will be ignored, and an empty message aborts the commit.  
  7. # On branch master  
  8. # Changes to be committed:  
  9. #       modified:   file1.txt  
  10. #  
Figure 3 (below) shows the result after the revert operation is completed. If we do a git log now, we'll see a new commit that reflects the contents before the previous commit. 
$ git log --oneline
11b7712 Revert "File with three lines"
b764644 File with three lines
7c709f0 File with two lines
9ef9173 File with one line



Revert or reset? 
Why would you choose to do a revert over a reset operation? If you have already pushed your chain of commits to the remote repository (where others may have pulled your code and started working with it), a revert is a nicer way to cancel out changes for them. This is because the Git workflow works well for picking up additional commits at the end of a branch, but it can be challenging if a set of commits is no longer seen in the chain when someone resets the branch pointer back. 

This brings us to one of the fundamental rules when working with Git in this manner: Making these kinds of changes in your local repository to code you haven't pushed yet is fine. But avoid making changes that rewrite history if the commits have already been pushed to the remote repository and others may be working with them. 

In short, if you rollback, undo, or rewrite the history of a commit chain that others are working with, your colleagues may have a lot more work when they try to merge in changes based on the original chain they pulled. If you must make changes against code that has already been pushed and is being used by others, consider communicating before you make the changes and give people the chance to merge their changes first. Then they can pull a fresh copy after the infringing operation without needing to merge. 

You may have noticed that the original chain of commits was still there after we did the reset. We moved the pointer and reset the code back to a previous commit, but it did not delete any commits. This means that, as long as we know the original commit we were pointing to, we can "restore" back to the previous point by simply resetting back to the original head of the branch: 
# git reset

A similar thing happens in most other operations we do in Git when commits are replaced. New commits are created, and the appropriate pointer is moved to the new chain. But the old chain of commits still exists. 

Rebase 
Now let's look at a branch rebase. Consider that we have two branches—master and feature—with the chain of commits shown in Figure 4 below. Master has the chain C4->C2->C1->C0 and feature has the chain C5->C3->C2->C1->C0. 

Fig. 4: Chain of commits for branches master and feature 

If we look at the log of commits in the branches, they might look like the following. (The C designators for the commit messages are used to make this easier to understand.
$ git log --oneline master
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0


$ git log --oneline feature
79768b8 C5
000f9ae C3
259bf36 C2
f33ae68 C1
5043e79 C0

I tell people to think of a rebase as a "merge with history" in Git. Essentially what Git does is take each different commit in one branch and attempt to "replay" the differences onto the other branch. So, we can rebase a feature onto master to pick up C4 (e.g., insert it into feature's chain). Using the basic Git commands, it might look like this: 
$ git checkout feature
$ git rebase master

First, rewinding head to replay your work on top of it...
Applying: C3
Applying: C5

Afterward, our chain of commits would look like Figure 5: 

Fig. 5: Chain of commits after the rebase command 

Again, looking at the log of commits, we can see the changes. 
$ git log --oneline master
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0


$ git log --oneline feature
c4533a5 C5
64f2047 C3
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0

Notice that we have C3' and C5'—new commits created as a result of making the changes from the originals "on top of" the existing chain in master. But also notice that the "original" C3 and C5 are still there—they just don't have a branch pointing to them anymore. If we did this rebase, then decided we didn't like the results and wanted to undo it, it would be as simple as: 
$ git reset 79768b8

With this simple change, our branch would now point back to the same set of commits as before the rebase operation—effectively undoing it (Figure 6). 

Fig. 6: After undoing the rebase operation 

What happens if you can't recall what commit a branch pointed to before an operation? Fortunately, Git again helps us out. For most operations that modify pointers in this way, Git remembers the original commit for you. In fact, it stores it in a special reference named ORIG_HEAD within the .git repository directory. That path is a file containing the most recent reference before it was modified. If we cat the file, we can see its contents. 
$ cat .git/ORIG_HEAD
79768b891f47ce06f13456a7e222536ee47ad2fe

We could use the reset command, as before, to point back to the original chain. Then the log would show this: 
$ git log --oneline feature
79768b8 C5
000f9ae C3
259bf36 C2
f33ae68 C1
5043e79 C0

Another place to get this information is in the reflog. The reflog is a play-by-play listing of switches or changes to references in your local repository. To see it, you can use the git reflog command
$ git reflog
79768b8 HEAD@{0}: reset: moving to 79768b
c4533a5 HEAD@{1}: rebase finished: returning to refs/heads/feature
c4533a5 HEAD@{2}: rebase: C5
64f2047 HEAD@{3}: rebase: C3
6a92e7a HEAD@{4}: rebase: checkout master
79768b8 HEAD@{5}: checkout: moving from feature to feature
79768b8 HEAD@{6}: commit: C5
000f9ae HEAD@{7}: checkout: moving from master to feature
6a92e7a HEAD@{8}: commit: C4
259bf36 HEAD@{9}: checkout: moving from feature to master
000f9ae HEAD@{10}: commit: C3
259bf36 HEAD@{11}: checkout: moving from master to feature
259bf36 HEAD@{12}: commit: C2
f33ae68 HEAD@{13}: commit: C1
5043e79 HEAD@{14}: commit (initial): C0

You can then reset to any of the items in that list using the special relative naming format you see in the log: 
$ git reset HEAD@{1}

Once you understand that Git keeps the original chain of commits around when operations "modify" the chain, making changes in Git becomes much less scary. This is one of Git's core strengths: being able to quickly and easily try things out and undo them if they don't work. 

Supplement 
FAQ - How do you revert to a specific tag in Git?

2019年5月10日 星期五

[ Python 常見問題 ] How to implement 'in' and 'not in' for Pandas dataframe

Source From Here 
Question 
How can I achieve the equivalents of SQL's IN and NOT IN? I have a list with the required values. Here's the scenario: 
>>> import pandas as pd 
>>> df = pd.DataFrame({'countries':['US', 'UK', 'Germany', 'China'], 'population':[100, 200, 300, 400]}) 
>>> countries = ['UK', 'China']

My current way of doing this is as follows: 
  1. rows = []  
  2. for ri, row in df.iterrows():  
  3.     if row.countries in countries:  
  4.         rows.append(ri)  
  5.   
  6. print(df.loc[rows])  
How-To 
You can use pd.Series.isin: 
* For "IN": somewhere.isin(list_of_place) 
* For "NOT IN": ~somewhere.isin(list_of_place)

As an example: 
  1. >>> df.head()  
  2.   countries  population  
  3. 0        US         100  
  4. 1        UK         200  
  5. 2   Germany         300  
  6. 3     China         400  
  7. >>> countries  
  8. ['UK', 'China']  
  9. >>> df[df.countries.isin(countries)]  
  10.   countries  population  
  11. 1        UK         200  
  12. 3     China         400  
  13. >>> df[~df.countries.isin(countries)]  
  14.   countries  population  
  15. 0        US         100  
  16. 2   Germany         300  

2019年5月8日 星期三

[Linux 文章收集] How to sort the output of ‘top’ command by memory or cpu usage

Source From Here 
Preface 
One of the programs that you can use to quickly see the various process information in Linux is the top command. The fact that the command can be run from virtually any command prompt and it is self updating makes it an extremely handy tool. This allows you can quickly find the processes that are consuming too much resources on the machine. 

In most cases, running the top command without any command line options is good enough to get the necessary information about the running processes. But there are some command line options that can be useful, one of which is the option to override the default sort field. 

You can use the -o command line option followed by the field name to sort the output by a particular stat or field. The field format supports the ability to specify the order of sort. You can use the ‘+’ to specify a high to low sort, while ‘-‘ can be used to specify the low to high sorting order. 

sort by memory usage 
So, if you want to sort the output by the memory used by each of the processes, you specify the %MEM field as the field to be sorted. 
$ top -o +%MEM # Sort by memory descendingly

The above command will sort the table by the MEM field. The MEM field displays the current resident share of the task or process with respect to the total available physical memory on the machine. The ‘+’ that precedes the field name (%MEM) specifies that the field will be sorted in descending order. The tasks that is eating the most memory will be displayed on top of the table. 

sort by CPU usage 
In order to sort by the CPU usage of the processes or tasks, you use the %CPU field just as in the example above. 
$ top -o +%CPU

The %CPU field displays the share of CPU time used by the task since the last update. The field is shown as a percentage of the total CPU time. 


Now, you could restrict the processes or tasks that are displayed as well. For example, you might want to get only the top 10 tasks that is using the most memory. In this case, you can filter using the head utility to display only the first 10 lines of the table. 
// -b :Batch-mode operation
$ top -b -o +%MEM | head -n 17

You will need to use the -b or the batch mode of the top command, so that you can filter the output using the head utility. Also, you must have noticed that the first 7 lines are used as summary by the top command, which means will need to print out the first 17 lines to get the top 10 processes. 

If you do not want to display the summary table on top, but just the process table with the top 10 tasks, then you can use the sed utility to display only specific lines. 
$ top -b -o +%MEM | sed -n '7,17p'

The above will print out just the line 7 through 17 which is the top 10 tasks sorted by the memory usage.

2019年4月27日 星期六

[ Python 文章收集 ] wxPython - Layout management in wxPython

Source From Here 
Layout management in wxPython 
A typical application consists of various widgets. Those widgets are placed inside container widgets. A programmer must manage the layout of the application. This is not an easy task. In wxPython it is possible to lay out widgets using absolute positioning or using sizers. 

Absolute Positioning 
The programmer specifies the position and the size of each widget in pixels. Absolute positioning has several disadvantages
* The size and the position of a widget do not change if we resize a window.
* Applications look different on various platforms.
* Changing fonts in the application might spoil the layout.
* If we decide to change our layout, we must completely redo our layout, which is tedious and time consuming.

There might be situations where we can possibly use absolute positioning. For instance, small test examples. But mostly, in real world programs, programmers use sizers

In our example we have a simple skeleton of a text editor. If we resize the window, the size of out wx.TextCtrl does not change as we would expect: 
absolute.py 
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3.   
  4. """  
  5. ZetCode wxPython tutorial  
  6.   
  7. In this example, we lay out widgets using  
  8. absolute positioning.  
  9.   
  10. author: Jan Bodnar  
  11. website: www.zetcode.com  
  12. last modified: April 2018  
  13. """  
  14.   
  15. import wx  
  16.   
  17.   
  18. class Example(wx.Frame):  
  19.   
  20.     def __init__(self, parent, title):  
  21.         super(Example, self).__init__(parent, title=title,  
  22.             size=(500400))  
  23.   
  24.         self.InitUI()  
  25.         self.Centre()  
  26.   
  27.     def InitUI(self):  
  28.   
  29.         self.panel = wx.Panel(self)  
  30.   
  31.         self.panel.SetBackgroundColour("gray")  
  32.   
  33.         self.LoadImages()  
  34.   
  35.         self.mincol.SetPosition((2020))  
  36.         self.bardejov.SetPosition((20160))  
  37.         self.rotunda.SetPosition((25020))  
  38.   
  39.   
  40.     def LoadImages(self):  
  41.   
  42.         self.mincol = wx.StaticBitmap(self.panel, wx.ID_ANY,  
  43.             wx.Bitmap("mincol.jpg", wx.BITMAP_TYPE_ANY))  
  44.   
  45.         self.bardejov = wx.StaticBitmap(self.panel, wx.ID_ANY,  
  46.             wx.Bitmap("bardejov.jpg", wx.BITMAP_TYPE_ANY))  
  47.   
  48.         self.rotunda = wx.StaticBitmap(self.panel, wx.ID_ANY,  
  49.             wx.Bitmap("rotunda.jpg", wx.BITMAP_TYPE_ANY))  
  50.   
  51.   
  52. def main():  
  53.     app = wx.App()  
  54.     ex = Example(None, title='Absolute positioning')  
  55.     ex.Show()  
  56.     app.MainLoop()  
  57.   
  58.   
  59. if __name__ == '__main__':  
  60.     main()  


In the above example, we position three images using absolute coordinates. With the SetPosition() method we place the image at exact position in coordinates we want. 

Using sizers 
Sizers do address all those issues we mentioned by absolute positioning. wxPython has the following sizers: 
wx.BoxSizer 
wx.StaticBoxSizer (tutorialspoint)
wx.GridSizer
wx.FlexGridSizer
wx.GridBagSizer

wx.BoxSizer 
wx.BoxSizer enables us to put several widgets into a row or a column. We can put another sizer into an existing sizer. This way we can create very complex layouts: 
  1. box = wx.BoxSizer(integer orient)  
  2. box.Add(wx.Window window, integer proportion=0, integer flag = 0, integer border = 0)  
The orientation can be wx.VERTICAL or wx.HORIZONTAL. Adding widgets into the wx.BoxSizer is done via the Add() method. In order to understand it, we need to look at its parameters. The proportion parameter defines the ratio of how widgets change in the defined orientation. Let's assume we have three buttons with the proportions 0, 1, and 2. They are added into a horizontal wx.BoxSizer. Button with proportion 0 will not change at all. Button with proportion 2 will change twice more than the one with proportion 1 in the horizontal dimension. 

With the flag parameter you can further configure the behaviour of the widgets within a wx.BoxSizer. We can control the border between the widgets. We add some space between widgets in pixels. In order to apply border we need to define sides, where the border will be used. We can combine them with the | operator; for instance wx.LEFT | wx.BOTTOM. We can choose between these flags: 
wx.LEFT
wx.RIGHT
wx.BOTTOM
wx.TOP
wx.ALL

The sizer is set to the panel widget with SetSizer() method. 
border.py 
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3.   
  4. """  
  5. ZetCode wxPython tutorial  
  6.   
  7. In this example we place a panel inside   
  8. another panel.  
  9.   
  10. author: Jan Bodnar  
  11. website: www.zetcode.com  
  12. last modified: April 2018  
  13. """  
  14.   
  15. import wx  
  16.   
  17.   
  18. class Example(wx.Frame):  
  19.   
  20.     def __init__(self, parent, title):  
  21.         super(Example, self).__init__(parent, title=title)  
  22.   
  23.         self.InitUI()  
  24.         self.Centre()  
  25.   
  26.     def InitUI(self):  
  27.   
  28.         panel = wx.Panel(self)  
  29.   
  30.         panel.SetBackgroundColour('#4f5049')  
  31.         vbox = wx.BoxSizer(wx.VERTICAL)  
  32.   
  33.         midPan = wx.Panel(panel)  
  34.         midPan.SetBackgroundColour('#ededed')  
  35.   
  36.         vbox.Add(midPan, wx.ID_ANY, wx.EXPAND | wx.ALL, 20)  
  37.         panel.SetSizer(vbox)  
  38.   
  39.   
  40. def main():  
  41.   
  42.     app = wx.App()  
  43.     ex = Example(None, title='Border')  
  44.     ex.Show()  
  45.     app.MainLoop()  
  46.   
  47.   
  48. if __name__ == '__main__':  
  49.     main()  
In the above example, we place some space around a panel by: 
  1. vbox.Add(midPan, wx.ID_ANY, wx.EXPAND | wx.ALL, 20)  
In border.py we have placed a 20 px border around a midPan panel. wx.ALL applies the border size to all four sides. 

If we use wx.EXPAND flag, our widget will use all the space that has been allotted to it. Lastly, we can also define the alignment of our widgets. We do it with the following flags: 
wx.ALIGN_LEFT
wx.ALIGN_RIGHT
wx.ALIGN_TOP
wx.ALIGN_BOTTOM
wx.ALIGN_CENTER_VERTICAL
wx.ALIGN_CENTER_HORIZONTAL
wx.ALIGN_CENTER



GoToClass example 
In the following example we introduce several important ideas. 
goto_class.py 
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3.   
  4.   
  5. """  
  6. ZetCode wxPython tutorial  
  7.   
  8. In this example we create a Go To class  
  9. layout with wx.BoxSizer.  
  10.   
  11. author: Jan Bodnar  
  12. website: www.zetcode.com  
  13. last modified: April 2018  
  14. """  
  15.   
  16. import wx  
  17.   
  18. class Example(wx.Frame):  
  19.   
  20.     def __init__(self, parent, title):  
  21.         super(Example, self).__init__(parent, title=title)  
  22.   
  23.         self.InitUI()  
  24.         self.Centre()  
  25.   
  26.     def InitUI(self):  
  27.   
  28.         panel = wx.Panel(self)  
  29.   
  30.         font = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT)  
  31.   
  32.         font.SetPointSize(9)  
  33.   
  34.         vbox = wx.BoxSizer(wx.VERTICAL)  
  35.   
  36.         hbox1 = wx.BoxSizer(wx.HORIZONTAL)  
  37.         st1 = wx.StaticText(panel, label='Class Name')  
  38.         st1.SetFont(font)  
  39.         hbox1.Add(st1, flag=wx.RIGHT, border=8)  
  40.         tc = wx.TextCtrl(panel)  
  41.         hbox1.Add(tc, proportion=1)  
  42.         vbox.Add(hbox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, border=10)  
  43.   
  44.         vbox.Add((-110))  
  45.   
  46.         hbox2 = wx.BoxSizer(wx.HORIZONTAL)  
  47.         st2 = wx.StaticText(panel, label='Matching Classes')  
  48.         st2.SetFont(font)  
  49.         hbox2.Add(st2)  
  50.         vbox.Add(hbox2, flag=wx.LEFT | wx.TOP, border=10)  
  51.   
  52.         vbox.Add((-110))  
  53.   
  54.         hbox3 = wx.BoxSizer(wx.HORIZONTAL)  
  55.         tc2 = wx.TextCtrl(panel, style=wx.TE_MULTILINE)  
  56.         hbox3.Add(tc2, proportion=1, flag=wx.EXPAND)  
  57.         vbox.Add(hbox3, proportion=1, flag=wx.LEFT|wx.RIGHT|wx.EXPAND,  
  58.             border=10)  
  59.   
  60.         vbox.Add((-125))  
  61.   
  62.         hbox4 = wx.BoxSizer(wx.HORIZONTAL)  
  63.         cb1 = wx.CheckBox(panel, label='Case Sensitive')  
  64.         cb1.SetFont(font)  
  65.         hbox4.Add(cb1)  
  66.         cb2 = wx.CheckBox(panel, label='Nested Classes')  
  67.         cb2.SetFont(font)  
  68.         hbox4.Add(cb2, flag=wx.LEFT, border=10)  
  69.         cb3 = wx.CheckBox(panel, label='Non-Project classes')  
  70.         cb3.SetFont(font)  
  71.         hbox4.Add(cb3, flag=wx.LEFT, border=10)  
  72.         vbox.Add(hbox4, flag=wx.LEFT, border=10)  
  73.   
  74.         vbox.Add((-125))  
  75.   
  76.         hbox5 = wx.BoxSizer(wx.HORIZONTAL)  
  77.         btn1 = wx.Button(panel, label='Ok', size=(7030))  
  78.         hbox5.Add(btn1)  
  79.         btn2 = wx.Button(panel, label='Close', size=(7030))  
  80.         hbox5.Add(btn2, flag=wx.LEFT|wx.BOTTOM, border=5)  
  81.         vbox.Add(hbox5, flag=wx.ALIGN_RIGHT|wx.RIGHT, border=10)  
  82.   
  83.         panel.SetSizer(vbox)  
  84.   
  85.   
  86. def main():  
  87.   
  88.     app = wx.App()  
  89.     ex = Example(None, title='Go To Class')  
  90.     ex.Show()  
  91.     app.MainLoop()  
  92.   
  93.   
  94. if __name__ == '__main__':  
  95.     main()  

Figure: A GoToClass window 

wx.GridSizer 
The wx.GridSizer lays out widgets in two dimensional table. Each cell within the table has the same size: 
  1. wx.GridSizer(int rows=1int cols=0int vgap=0int hgap=0)  
In the constructor we specify the number of rows and columns in the table and the vertical and horizontal space between our cells. In our example we create a skeleton of a calculator. 
calculator.py 
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3.   
  4.   
  5. """  
  6. ZetCode wxPython tutorial  
  7.   
  8. In this example we create a layout  
  9. of a calculator with wx.GridSizer.  
  10.   
  11. author: Jan Bodnar  
  12. website: www.zetcode.com  
  13. last modified: April 2018  
  14. """  
  15.   
  16. import wx  
  17.   
  18.   
  19. class Example(wx.Frame):  
  20.   
  21.     def __init__(self, parent, title):  
  22.         super(Example, self).__init__(parent, title=title)  
  23.   
  24.         self.InitUI()  
  25.         self.Centre()  
  26.   
  27.   
  28.     def InitUI(self):  
  29.   
  30.         menubar = wx.MenuBar()  
  31.         fileMenu = wx.Menu()  
  32.         menubar.Append(fileMenu, '&File')  
  33.         self.SetMenuBar(menubar)  
  34.   
  35.         vbox = wx.BoxSizer(wx.VERTICAL)  
  36.         self.display = wx.TextCtrl(self, style=wx.TE_RIGHT)  
  37.         vbox.Add(self.display, flag=wx.EXPAND|wx.TOP|wx.BOTTOM, border=4)  
  38.         gs = wx.GridSizer(5455)  
  39.   
  40.         gs.AddMany( [(wx.Button(self, label='Cls'), 0, wx.EXPAND),  
  41.             (wx.Button(self, label='Bck'), 0, wx.EXPAND),  
  42.             (wx.StaticText(self), wx.EXPAND),  
  43.             (wx.Button(self, label='Close'), 0, wx.EXPAND),  
  44.             (wx.Button(self, label='7'), 0, wx.EXPAND),  
  45.             (wx.Button(self, label='8'), 0, wx.EXPAND),  
  46.             (wx.Button(self, label='9'), 0, wx.EXPAND),  
  47.             (wx.Button(self, label='/'), 0, wx.EXPAND),  
  48.             (wx.Button(self, label='4'), 0, wx.EXPAND),  
  49.             (wx.Button(self, label='5'), 0, wx.EXPAND),  
  50.             (wx.Button(self, label='6'), 0, wx.EXPAND),  
  51.             (wx.Button(self, label='*'), 0, wx.EXPAND),  
  52.             (wx.Button(self, label='1'), 0, wx.EXPAND),  
  53.             (wx.Button(self, label='2'), 0, wx.EXPAND),  
  54.             (wx.Button(self, label='3'), 0, wx.EXPAND),  
  55.             (wx.Button(self, label='-'), 0, wx.EXPAND),  
  56.             (wx.Button(self, label='0'), 0, wx.EXPAND),  
  57.             (wx.Button(self, label='.'), 0, wx.EXPAND),  
  58.             (wx.Button(self, label='='), 0, wx.EXPAND),  
  59.             (wx.Button(self, label='+'), 0, wx.EXPAND) ])  
  60.   
  61.         vbox.Add(gs, proportion=1, flag=wx.EXPAND)  
  62.         self.SetSizer(vbox)  
  63.   
  64.   
  65. def main():  
  66.   
  67.     app = wx.App()  
  68.     ex = Example(None, title='Calculator')  
  69.     ex.Show()  
  70.     app.MainLoop()  
  71.   
  72.   
  73. if __name__ == '__main__':  
  74.     main()  
Notice how we managed to put a space between the Bck and the Close buttons. We simply put an empty wx.StaticText there. In our example we have used the AddMany() method. It is a convenience method for adding multiple widgets at one time. 

Widgets are placed inside the table in the order, they are added. The first row is filled first, then the second row etc: 

Figure: Calculator 

wx.FlexGridSizer 
This sizer is similar to wx.GridSizer. It does also lay out its widgets in a two dimensional table. It adds some flexibility to it. wx.GridSizer cells are of the same size. All cells in wx.FlexGridSizer have the same height in a row. All cells have the same width in a column. But all rows and columns are not necessarily the same height or width
  1. wx.FlexGridSizer(int rows=1int cols=0int vgap=0int hgap=0)  
rows and cols specify the number of rows and columns in a sizer. vgap and hgap add some space between widgets in both directions. 

Many times developers have to develop dialogs for data input and modification. I find wx.FlexGridSizer suitable for such a task. A developer can easily set up a dialog window with this sizer. It is also possible to accomplish this with wx.GridSizer, but it would not look nice, because of the constraint that each cell must have the same size. 
review.py 
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3.   
  4. """  
  5. ZetCode wxPython tutorial  
  6.   
  7. In this example we create review  
  8. layout with wx.FlexGridSizer.  
  9.   
  10. author: Jan Bodnar  
  11. website: www.zetcode.com  
  12. last modified: April 2018  
  13. """  
  14.   
  15. import wx  
  16.   
  17. class Example(wx.Frame):  
  18.   
  19.     def __init__(self, parent, title):  
  20.         super(Example, self).__init__(parent, title=title)  
  21.   
  22.         self.InitUI()  
  23.         self.Centre()  
  24.         self.Show()  
  25.   
  26.     def InitUI(self):  
  27.   
  28.         panel = wx.Panel(self)  
  29.   
  30.         hbox = wx.BoxSizer(wx.HORIZONTAL)  
  31.   
  32.         fgs = wx.FlexGridSizer(32925)  
  33.   
  34.         title = wx.StaticText(panel, label="Title")  
  35.         author = wx.StaticText(panel, label="Author")  
  36.         review = wx.StaticText(panel, label="Review")  
  37.   
  38.         tc1 = wx.TextCtrl(panel)  
  39.         tc2 = wx.TextCtrl(panel)  
  40.         tc3 = wx.TextCtrl(panel, style=wx.TE_MULTILINE)  
  41.   
  42.         fgs.AddMany([(title), (tc1, 1, wx.EXPAND), (author),  
  43.             (tc2, 1, wx.EXPAND), (review, 1, wx.EXPAND), (tc3, 1, wx.EXPAND)])  
  44.   
  45.         fgs.AddGrowableRow(21)    # Only cell(2, *) can grow in row direction  
  46.         fgs.AddGrowableCol(11)     # Only cell(*, 1) can grow in column direction      
  47.   
  48.         hbox.Add(fgs, proportion=1, flag=wx.ALL|wx.EXPAND, border=15)  
  49.         panel.SetSizer(hbox)  
  50.   
  51.   
  52. def main():  
  53.   
  54.     app = wx.App()  
  55.     ex = Example(None, title='Review')  
  56.     ex.Show()  
  57.     app.MainLoop()  
  58.   
  59.   
  60. if __name__ == '__main__':  
  61.     main()  
One code snippet is worthy of more description: 
  1. fgs.AddGrowableRow(21)  
  2. fgs.AddGrowableCol(11)  
We make the third row and second column growable. This way we let the text controls grow when the window is resized. The first two text controls will grow in horizontal direction, the third one will grow in both directions. We must not forget to make the widgets expandable with wx.EXPAND in order to make it work. 


wx.GridBagSizer 
wx.GridBagSizer is the most flexible sizer in wxPython. to use. This kind of sizer is not typical only for wxPython. We can find it in other toolkits as well. This sizer enables explicit positioning of items. Items can also optionally span more than one row or column. The wx.GridBagSizer has a simple constructor. 
  1. wx.GridBagSizer(integer vgap, integer hgap)  
The vertical and the horizontal gap defines the space in pixels used among all children. We add items to the grid with the Add() method. 
  1. Add(self, item, tuple pos, tuple span=wx.DefaultSpan, integer flag=0,   
  2.     integer border=0, userData=None)  
Item is a widget that you insert into the grid. The pos specifies the position in the virtual grid. The top-left cell has pos of (0, 0). The span is an optional spanning of the widget; e.g. a span of (3, 2) spans a widget across 3 rows and 2 columns. The flag and border were discussed earlier by wx.BoxSizer. The items in the grid can change their size or keep the default size, when the window is resized. If we want your items to grow and shrink, we can use the following two methods: 
AddGrowableRow(integer row)
AddGrowableCol(integer col)

Rename window example 
In our first example, we create a Rename window. It will have one wx.StaticText, one wx.TextCtrl and two wx.Button widgets. 
rename.py 
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3.   
  4. """  
  5. ZetCode wxPython tutorial  
  6.   
  7. In this example we create a rename layout  
  8. with wx.GridBagSizer.  
  9.   
  10. author: Jan Bodnar  
  11. website: www.zetcode.com  
  12. last modified: April 2018  
  13. """  
  14.   
  15. import wx  
  16.   
  17.   
  18. class Example(wx.Frame):  
  19.   
  20.     def __init__(self, parent, title):  
  21.         super(Example, self).__init__(parent, title=title)  
  22.   
  23.         self.InitUI()  
  24.         self.Centre()  
  25.   
  26.     def InitUI(self):  
  27.   
  28.         panel = wx.Panel(self)  
  29.         sizer = wx.GridBagSizer(44)  
  30.   
  31.         text = wx.StaticText(panel, label="Rename To")  
  32.         sizer.Add(text, pos=(00), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)  
  33.   
  34.         tc = wx.TextCtrl(panel)  
  35.         sizer.Add(tc, pos=(10), span=(15),  
  36.             flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=5)  
  37.   
  38.         buttonOk = wx.Button(panel, label="Ok", size=(9028))  
  39.         buttonClose = wx.Button(panel, label="Close", size=(9028))  
  40.         sizer.Add(buttonOk, pos=(33))  
  41.         sizer.Add(buttonClose, pos=(34), flag=wx.RIGHT|wx.BOTTOM, border=10)  
  42.   
  43.         sizer.AddGrowableCol(1)  
  44.         sizer.AddGrowableRow(2)  
  45.         panel.SetSizer(sizer)  
  46.   
  47.   
  48. def main():  
  49.   
  50.     app = wx.App()  
  51.     ex = Example(None, title='Rename')  
  52.     ex.Show()  
  53.     app.MainLoop()  
  54.   
  55.   
  56. if __name__ == '__main__':  
  57.     main()  

Figure: Rename window 

We must look at the window as a one big grid table. Firstly, the text "Rename to" goes to the left upper corner. So we specify the (0, 0) position. And we add some space to the bottom, left, and bottom. 
  1. text = wx.StaticText(panel, label="Rename To")  
  2. sizer.Add(text, pos=(00), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=10)  
The wx.TextCtrl goes to the beginning of the second row (1, 0). Remember, that we count from zero. It expands 1 row and 5 columns (1, 5). And we put 5 pixels of space to the left and to the right of the widget: 
  1. tc = wx.TextCtrl(panel)  
  2. sizer.Add(tc, pos=(10), span=(15),   
  3.     flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=5)  
We put two buttons into the fourth row. The third row is left empty, so that we have some space between the wx.TextCtrl and the buttons. We put the OK button into the fourth column and the Close button into the fifth one. Notice that once we apply some space to one widget, it is applied to the whole row. That's why we did not specify bottom space for the OK button. A careful reader might notice that we did not specify any space between the two buttons; that is, we did not put any space to the right of the OK button, or to the right of the Close button. In the constructor of the wx.GridBagSizer, we put some space between all widgets. So there is some space already. 
  1. sizer.Add(buttonOk, pos=(33))  
  2. sizer.Add(buttonClose, pos=(34), flag=wx.RIGHT|wx.BOTTOM, border=10)  
The last thing we must do is to make our dialog resizable. We make the second column and the third row growable. Now we can expand or shrink our window. Try to comment those two lines and see what happens. 
  1. sizer.AddGrowableCol(1)  
  2. sizer.AddGrowableRow(2)  
New class example 
In the next example is we create a window, which can be found in JDeveloper. It is a window for creating a new class in Java. 
new_class.py 
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3.   
  4. """  
  5. ZetCode wxPython tutorial  
  6.   
  7. In this example we create a new class layout  
  8. with wx.GridBagSizer.  
  9.   
  10. author: Jan Bodnar  
  11. website: www.zetcode.com  
  12. last modified: April 2018  
  13. """  
  14.   
  15. import wx  
  16.   
  17. class Example(wx.Frame):  
  18.   
  19.     def __init__(self, parent, title):  
  20.         super(Example, self).__init__(parent, title=title)  
  21.   
  22.         self.InitUI()  
  23.         self.Centre()  
  24.   
  25.     def InitUI(self):  
  26.   
  27.         panel = wx.Panel(self)  
  28.   
  29.         sizer = wx.GridBagSizer(55)  
  30.   
  31.         text1 = wx.StaticText(panel, label="Java Class")  
  32.         sizer.Add(text1, pos=(00), flag=wx.TOP|wx.LEFT|wx.BOTTOM,  
  33.             border=15)  
  34.   
  35.         icon = wx.StaticBitmap(panel, bitmap=wx.Bitmap('exec.png'))  
  36.         sizer.Add(icon, pos=(04), flag=wx.TOP|wx.RIGHT|wx.ALIGN_RIGHT,  
  37.             border=5)  
  38.   
  39.         line = wx.StaticLine(panel)  
  40.         sizer.Add(line, pos=(10), span=(15),  
  41.             flag=wx.EXPAND|wx.BOTTOM, border=10)  
  42.   
  43.         text2 = wx.StaticText(panel, label="Name")  
  44.         sizer.Add(text2, pos=(20), flag=wx.LEFT, border=10)  
  45.   
  46.         tc1 = wx.TextCtrl(panel)  
  47.         sizer.Add(tc1, pos=(21), span=(13), flag=wx.TOP|wx.EXPAND)  
  48.   
  49.         text3 = wx.StaticText(panel, label="Package")  
  50.         sizer.Add(text3, pos=(30), flag=wx.LEFT|wx.TOP, border=10)  
  51.   
  52.         tc2 = wx.TextCtrl(panel)  
  53.         sizer.Add(tc2, pos=(31), span=(13), flag=wx.TOP|wx.EXPAND,  
  54.             border=5)  
  55.   
  56.         button1 = wx.Button(panel, label="Browse...")  
  57.         sizer.Add(button1, pos=(34), flag=wx.TOP|wx.RIGHT, border=5)  
  58.   
  59.         text4 = wx.StaticText(panel, label="Extends")  
  60.         sizer.Add(text4, pos=(40), flag=wx.TOP|wx.LEFT, border=10)  
  61.   
  62.         combo = wx.ComboBox(panel)  
  63.         sizer.Add(combo, pos=(41), span=(13),  
  64.             flag=wx.TOP|wx.EXPAND, border=5)  
  65.   
  66.         button2 = wx.Button(panel, label="Browse...")  
  67.         sizer.Add(button2, pos=(44), flag=wx.TOP|wx.RIGHT, border=5)  
  68.   
  69.         sb = wx.StaticBox(panel, label="Optional Attributes")  
  70.   
  71.         boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)  
  72.         boxsizer.Add(wx.CheckBox(panel, label="Public"),  
  73.             flag=wx.LEFT|wx.TOP, border=5)  
  74.         boxsizer.Add(wx.CheckBox(panel, label="Generate Default Constructor"),  
  75.             flag=wx.LEFT, border=5)  
  76.         boxsizer.Add(wx.CheckBox(panel, label="Generate Main Method"),  
  77.             flag=wx.LEFT|wx.BOTTOM, border=5)  
  78.         sizer.Add(boxsizer, pos=(50), span=(15),  
  79.             flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT , border=10)  
  80.   
  81.         button3 = wx.Button(panel, label='Help')  
  82.         sizer.Add(button3, pos=(70), flag=wx.LEFT, border=10)  
  83.   
  84.         button4 = wx.Button(panel, label="Ok")  
  85.         sizer.Add(button4, pos=(73))  
  86.   
  87.         button5 = wx.Button(panel, label="Cancel")  
  88.         sizer.Add(button5, pos=(74), span=(11),  
  89.             flag=wx.BOTTOM|wx.RIGHT, border=10)  
  90.   
  91.         sizer.AddGrowableCol(2)  
  92.   
  93.         panel.SetSizer(sizer)  
  94.         sizer.Fit(self)  
  95.           
  96.   
  97. def main():  
  98.   
  99.     app = wx.App()  
  100.     ex = Example(None, title="Create Java Class")  
  101.     ex.Show()  
  102.     app.MainLoop()  
  103.   
  104.   
  105. if __name__ == '__main__':  
  106.     main()  
 
Figure: New class window 

This part of the wxPython tutorial was dedicated to layout management. 

Supplement 
Tutorialspoint - wxPython - GridBagSizer

[Git 文章收集] How to reset, revert, and return to previous states in Git

Source From  Here   Preface   One of the lesser understood ( and appreciated ) aspects of working with Git is  how easy it is to get back ...