Jack Diederich
[Python-3000] PEP Draft: Class Decorators
Cesar Otero - IBM DevelopWorks White Paper
Python 3 primer, Part 2: Advanced topics
Metaclasses, decorators, and other strange creatures
Monday, April 26, 2010
Python Introspection/Reflection Utility Class
So the code below is for a python module 'mir.py', and contains a class 'Mir' and a rather thin main method 'run()' which demos the class.
class Mir:
"""mirror introspection/reflection class"""
meth_lookup_token_len = len('<function')
meth_type_lookup = {
'<bound me' : 'instance',
'<function' : 'static',
'<method-wr' : 'wrapper',
'<built-in ' : 'built-in'
}
def __init__(self):
"""docstring for initializer"""
pass
@staticmethod
def ins(target,show_magic_meths=False):
lines = []
"""provide basic information on the target"""
# column widthss
c1 = 20
c2 = 20
c3 = 40
field_names = []
method_names = []
mangled_field_names = []
dir_list = dir(target)
for ob in dir_list:
if (callable(getattr(target, ob))):
method_names.append(ob)
else:
field_names.append(ob)
# FIELDS --------------------------------------
# double leading and trailing underscore
magic_fields = []
# starts and ends with alphabetic
normal_fields = []
# double leading underscore # mangledFields = []
# single leading underscore # privateFields = []
for field_name in field_names:
a = getattr(target, field_name)
l = len(field_name)
# magic fields
if (field_name[0:2] == '__'):
if (field_name[l - 2 : l] == '__'):
magic_fields.append(field_name)
else:
mangled_field_names.append(field_names)
else:
normal_fields.append(field_name)
if '__doc__' in magic_fields:
docstring = getattr(target, '__doc__')
else:
docstring = 'no doc string'
if '__module__' in magic_fields:
moduleName = getattr(target, '__module__')
else:
moduleName = 'no module'
# METHODS
# class methods
# instance methods
# - constructor
# - vanilla
static_methods = []
instance_methods = []
magic_methods = []
meth_info = []
for method_name in method_names:
# DETERMINE METHOD TYPE = INSTANCE, STATIC
a = getattr(target, method_name)
try:
s = (str(a))
token = s[0:Mir.meth_lookup_token_len+1]
meth_type = Mir.meth_type_lookup[token]
except:
meth_type = s[0:c2]
else:
pass
# GET METHOD DOC-STRING
meth_docstring = getattr(a, '__doc__')
if (meth_docstring == None):
meth_docstring = ''
else:
meth_docstring = meth_docstring.replace('\n', ' | ')
if (meth_type == 'static'):
static_methods.append((method_name, meth_docstring))
elif (meth_type == 'instance'):
instance_methods.append((method_name, meth_docstring))
else:
pass
L = len(method_name)
prefix = (method_name[0:2] == '__')
suffix = (method_name[L-2:L] == '__')
if (prefix and suffix):
magic_methods.append(method_name)
meth_info.append((method_name, meth_type, meth_docstring))
lines.append('----------------------------------------------------------------------')
lines.append('target = ' + str(target))
lines.append('target type = ' + str(type(target)))
lines.append('source module: %s' % moduleName)
lines.append('----------------------------------------------------------------------')
lines.append('docstring: %s' % docstring)
lines.append('')
lines.append('----------------------------------------------------------------------')
lines.append('FIELDS')
lines.append('---------------')
# static
# class
# instance
for field_name in normal_fields:
a = getattr(target, field_name)
lines.append(field_name.ljust(20) + str(a).ljust(30))
if (show_magic_meths):
lines.append('----------------------------------------------------------------------')
lines.append('METHODS - MAGIC')
lines.append('---------------')
for (meth_name, meth_type, methDoc) in meth_info:
if (meth_name in magic_methods):
lines.append(meth_name.ljust(c1) + meth_type.ljust(c2) + methDoc.ljust(c3))
lines.append('----------------------------------------------------------------------')
lines.append('METHODS - NON-MAGIC')
lines.append('---------------')
for (meth_name, meth_type, methDoc) in meth_info:
if (meth_name not in magic_methods):
lines.append(meth_name.ljust(c1) + meth_type.ljust(c2) + methDoc.ljust(c3))
return lines
@staticmethod
def inspect(target):
lines = Mir.ins(target)
for line in lines:
print(line)
@staticmethod
def ins2f(target, fname):
file = open(fname, 'w')
for line in Mir.ins(target):
file.write(line + '\n')
file.close()
# #########################################################
def run():
lis = []
Mir.inspect(lis)
if __name__ == '__main__':
Sunday, April 25, 2010
Some OO Concepts in Python
PRIVATE VS PUBLIC
the short answer is no - in other words, this is not productively supported.
use the convention of prefixing 'would otherwise be private if the dumb language supported it' fields with an underscore, e.g.
CLASS vs INSTANCE OBJECTS
Class Objects support
- instantiation
- attribute referencing
Making our descriptively named class more accurately self-referential:
Finally, just to avoid any lurking confusion, THE FOLLOWING IS FLAWED
and fails miserably, raising a NameError exception;
-------
So, annotating a method with the @classmethod produces something quite similar to a C# static method. In other words, within the class method only local and class level references are possible, or rather, no instance level field or method is accessible (short of instantiating an object of that class within the class method, and calling the method on that instance).
Where C# and python differ, however, is that in C# to call the static method DoStuff() on class TheClass, you would have something like this
In other words, you can't have something like this, where you call the class method on an instance variable
The compiler will kick you in the head.
In python, however, there is no such limitation. You can happily call a class method on an instance variable (the class method still won't have access to the instance level scope).
ABSTRACT BASE CLASSES & QUASI-INTERFACES
- ABCs - PEP 3119 = http://www.python.org/dev/peps/pep-3119/
- from the pythondocs: http://docs.python.org/library/abc.html
- James Tauber's take on interfaces: http://jtauber.com/blog/2007/03/04/interfaces_versus_abstract_base_classes_in_python/
the short answer is no - in other words, this is not productively supported.
use the convention of prefixing 'would otherwise be private if the dumb language supported it' fields with an underscore, e.g.
class TheClass:
def __init__(self):
self._nominallyPrivateField = 'private'
CLASS vs INSTANCE OBJECTS
Class Objects support
- instantiation
- attribute referencing
class TheClass:
classLevelField = 'class level field'
def __init__(self):
self.instanceLevelField = 'instance level field'
Making our descriptively named class more accurately self-referential:
class TheClass:
classLevelField = 'class level field'
def __init__(self):
self._nominallyPrivateInstanceLevelField = 'only nominally private instance level field'
Finally, just to avoid any lurking confusion, THE FOLLOWING IS FLAWED
class TheClass:
classLevelField = 'class level field'
self._nominallyPrivateInstanceLevelField = 'only nominally private instance level field'
def __init__(self):
pass
and fails miserably, raising a NameError exception;
NameError: name 'self' is not defined
-------
So, annotating a method with the @classmethod produces something quite similar to a C# static method. In other words, within the class method only local and class level references are possible, or rather, no instance level field or method is accessible (short of instantiating an object of that class within the class method, and calling the method on that instance).
Where C# and python differ, however, is that in C# to call the static method DoStuff() on class TheClass, you would have something like this
TheClass.DoStuff()
In other words, you can't have something like this, where you call the class method on an instance variable
TheClass myClass = new TheClass();
myClass.DoStuff();
The compiler will kick you in the head.
In python, however, there is no such limitation. You can happily call a class method on an instance variable (the class method still won't have access to the instance level scope).
ABSTRACT BASE CLASSES & QUASI-INTERFACES
- ABCs - PEP 3119 = http://www.python.org/dev/peps/pep-3119/
- from the pythondocs: http://docs.python.org/library/abc.html
- James Tauber's take on interfaces: http://jtauber.com/blog/2007/03/04/interfaces_versus_abstract_base_classes_in_python/
Thursday, April 15, 2010
To Force a Line-Break in a VS2008 Method Summary Comment
enclose the target text in tags.
this will force a line-break afterwards.
note that a line with will simply be ignored, and will not produce and empty line as might be expected.
this will force a line-break afterwards.
note that a line with
Saturday, April 10, 2010
Python Resources
WHAT IS PYTHON ?
- interpreted
- compiled to intermediate bytecode
- dynamically typed
- functional, object oriented and imperative paradigms
SOME PYTHON USERS
- google
- facebook ?
- nasa
A COUPLE OF NOTES ON VERSIONING
- latest release = 3.?
- 2.7 = offers features from 3.0 but and backwards compatibility with 2.x
get the latest version from the OFFICIAL DOWNLOAD PAGE
Python-specific Integrated Development Environments (IDE's)
- #1 - GEANY Light-Weight w. Introspective Predictive Text !!
- netbeans 6.5 python early-access stand-alone
- netbeans java with python plugin
- eclipse with pydev plugin
- SCITE text editor
TUTORIALS
Good places to start
- The Official Docs
- Dive into Python
STYLE GUIDEs
- PEP 8 - an Official Style Guide
- official google python style guide
- 'Coding Like a Pythonista' - Idiomatic Python
UNIT TESTING
- unittest
OBJECT ORIENTED PARADIGM
- decorators, decorators
- abstract base classes
- meta_classes
- properties, properties
- staticmethods & classmethods
FUNCTIONAL PROGRAMMING PARADIGM
- map, reduce, filter @ pythontips.com
WIDGET KITS
- pygtk
- wxpython
- light-weight - tkinter
WEB
- django
NUMERIC AND SCIENTIFIC LIBRARIES
- numpy and scipy
PLOTTING
- matplotlib
LOGGING and other timber-related activities
Why Python ?
by Eric S Raymond, author of 'The Cathedral and the Bazaar"
- interpreted
- compiled to intermediate bytecode
- dynamically typed
- functional, object oriented and imperative paradigms
SOME PYTHON USERS
- facebook ?
- nasa
A COUPLE OF NOTES ON VERSIONING
- latest release = 3.?
- 2.7 = offers features from 3.0 but and backwards compatibility with 2.x
get the latest version from the OFFICIAL DOWNLOAD PAGE
Python-specific Integrated Development Environments (IDE's)
- #1 - GEANY Light-Weight w. Introspective Predictive Text !!
- netbeans 6.5 python early-access stand-alone
- netbeans java with python plugin
- eclipse with pydev plugin
- SCITE text editor
TUTORIALS
Good places to start
- The Official Docs
- Dive into Python
STYLE GUIDEs
- PEP 8 - an Official Style Guide
- official google python style guide
- 'Coding Like a Pythonista' - Idiomatic Python
UNIT TESTING
- unittest
OBJECT ORIENTED PARADIGM
- decorators, decorators
- abstract base classes
- meta_classes
- properties, properties
- staticmethods & classmethods
FUNCTIONAL PROGRAMMING PARADIGM
- map, reduce, filter @ pythontips.com
WIDGET KITS
- pygtk
- wxpython
- light-weight - tkinter
WEB
- django
NUMERIC AND SCIENTIFIC LIBRARIES
- numpy and scipy
PLOTTING
- matplotlib
LOGGING and other timber-related activities
Why Python ?
by Eric S Raymond, author of 'The Cathedral and the Bazaar"
Subscribe to:
Posts (Atom)