Monday, May 29, 2006

Python note: get your ip address

Here is a small platform independent script for you to get the IP address for the current machine.

import socket
print socket.gethostbyname(socket.gethostname())

Sunday, May 28, 2006

Python note: SimpleHTTPServer note

Special notice for SimpleHTTPServer:

1. Read more of the source code! The SimpleHTTPRequestHandler is initialised, does the job and then dissappears. To retain it code must be edited.

2. Notice that each HTTP request asks only one response. This is HTTP protocol, and more responses will cause problems.

Tuesday, May 23, 2006

C++ note: references vs pointers

Use references when the target is a fixed object:

a_class* const a_inst=&a; => a_class &a_inst=a;

It's ideal to use references when passing a parameter to a function, because they probably won't move. However, when using references for return values we must be careful that the original value is in the heap and not in the stack (local varaible). It's more natural to return a pointer.

Use pointers in the cases of iterating through a lot of objects. Actually, iteration is probably the best place to use pointers. Also when the address is needed explicitly pointer is the only choice.

Saturday, May 13, 2006

VIM note: abbreviations

Command :abbr (:ab) sets abbreviations for strings. For example, with

:abbr #a hello

You could use #a[ENTER] in the INSERT mode to write "hello". This is useful for writing comment.

In my python files, I usually use comment blocks like

#--------------------------------------------
#
# Function header
#
#--------------------------------------------


This could neatly be done by putting some abbr commands to the .vimrc file

Note:
1. You must use # plus one letter for abbreviation names
2. Under windows the vimrc file is _vimrc, and you must make an environment variable VIM.

Wednesday, May 10, 2006

C++ note: virtual inheritance

The format

public class C: virtual B {...}

The main reason for virtual inheritance is for the diamond structure - B extends D, C extends D and A extends B, C. Without virtual mark, the instances of A will include data slots defined in both B and C, while the data slots defined in B and C will each include the data slots from D .

Python's will always have a diamond structure, because it always uses references. Of course Java does not have such problems.

Python note: when you get a lot of instances

Some classes has quite a lot of instances, and it's important to reduce the memory consumption by these objects. I blog two ways of doing it by Python.

First is using __slots__. Define this in the class definition, with a sequence type (normally tuple, but never string). For example,

class C(object):
...__slots__ = "foo", "bar"


This will make the instances of the class only have two attributes "foo" and "bar". Methods are the same, and they just need to be defined in the normal way.

The reason that __slots__ might save memory is that it saves the need of making a dictionary object in every instance to store possible attributes. This works when there are a large number of instances.

The second way is the flyweight pattern. The idea of this pattern is reusing existing objects.

For example, an email client maintains many messages. Each mail could be tagged with "read", "flag" etc. One client might contain huge number of email instances viewed at a time, and it's wise to reuse certain property instances for each email.

Lastly, my view regarding patterns is that they are not something to be enjoyed as programming tips. Different problems must be solved in different ways, and applying a pattern blindly is of no good. However, reading some patterns could give me hints in problem solving. And a byproduct is that I would know what people in the Java world are talking about ;-)

Wednesday, May 03, 2006

Python note: a file merger

Problem: I've got two folders, containing images from two Cannon camera. They were taken the same day. Unfortunately, these two cameras gave the same names to their pictures. I wanted to merge these two folders, with more powerful functionalities.

Script: This script takes in two folders, moving files from one folder to the other one. When there are duplicate file names, it compares the files. If the files are really duplicated, it only keeps one copy. If the files are different in content, they are renamed to different names by adding postfixes.

Code: The following python source
#
# merge files - merge two folders with no duplicate files
#
g_sWelcome = """
merge_files - merge files from two directories into one.

The files from the "from" directory will be moved to the "to" directory, while
duplicated files will be removed. If two files are in the same name but are
different in signature (revision time, size), the new one will be renamed.

Author: Yue Zhang, 2006
"""
import sys,os
import filecmp
import shutil
#
# Given a path, filename and extention, return a full path name without collision
#
def fileid_alloc(sPath, sPathFrom, sFileName, sExtension):
...global nDuplicateName, nDuplicateContent
...nIndex = 0
...sNewFileName = os.path.join(sPath, sFileName + sExtension)
...if os.path.exists(sNewFileName):
......nDuplicateName += 1
......if filecmp.cmp(sNewFileName, os.path.join(sPathFrom, sFileName + sExtension)):
.........nDuplicateContent += 1
.........return sNewFileName
...while os.path.exists(sNewFileName):
......nIndex += 1
......sNewFileName = os.path.join(sPath, sFileName + str(nIndex) + sExtension)
...return sNewFileName
#
# Main function
#
def merge_files(folder_from, folder_to):
...for sFullFileName in os.listdir(folder_from):
......sFileName, sExtension = os.path.splitext(sFullFileName)
......sNewFileName = fileid_alloc(folder_to, folder_from, sFileName, sExtension)
......shutil.move(os.path.join(folder_from, sFullFileName), sNewFileName)
#
# Main entry
#
if __name__ == '__main__':
...global nDuplicateName, nDuplicateContent
...nDuplicateName = 0
...nDuplicateContent = 0
...print g_sWelcome
...if len(sys.argv) != 3:
......print "Usage: merge_files.py folder_from folder_to"
......sys.exit(0)
...merge_files(sys.argv[1], sys.argv[2])
...print "In all %d duplicate file names processed, among which %d
............duplicate contents are merged and the rest are allocated new name."
............% (nDuplicateName, nDuplicateContent)

Disclaimer
: I give no warranty of responsibilities of use of the code, though I have tested this code with my own photos.