Artificial Code

This is Noah Gift's Coding Blog. I only talk about coding and technical stuff here, and that is mostly Python, although I will mix in some other languages, and talk about Artificial Intelligence.

Tuesday, August 25, 2009

10 Ways To Let People Know You're A Bad Python Programmer

1. Write "God" functions

These functions often stretch well over several hundred lines of code, and often have some form of action in the title, like "doMyStuff", or "doComplicatedSequence". Also, make sure you name the God functions or methods in camel case, so it is very clear you never bothered to read the Python Style Guide: PEP 8.

Extra Credit:

* Add huge blocks of commented code and mix them in the middle.
* Add comments in the doc string or anywhere, that say, this is "magic", or "bad" and needs to be rewritten.

2. Never return anything in a function, especially not some type of value that could demonstrate your function succeeded or failed.

This makes your code almost impossible to test and makes it clear you think programming is "magic". After all, who cares if a function does what you wanted?

3. Never write a test...EVER.

Claim testing is impossible where you work because it is different. Make up excuses like, "I am used to other people testing my code" (This one sounds especially good if your a former .NET developer.) If you really want to go all the way, don't even bother looking up how to write a unit test. Convince yourself it is impossibly complicated and not worthwhile and that people won't notice.

4. Call Perl from Python

This is an oldie but a goodie, but a lot of bad programmers don't realize they can make their Python code even worse, if they embed a bunch of untested, legacy, Perl code in it. There is a Perl/Python module that makes this a snap.

Extra Credit:

* Call a nest of Perl regular expressions from Python instead of doing a doing something like:


if "string" in variable:


* Brag that you called Perl from Python because it was "quicker" to experienced Python programmers.

5. Screw Control Flow

If you can write a few statements, then mix in some functions, then maybe define a class, then write more statements, you have "screwed" Control Flow successfully. Something like below is a good starting point:




#!/usr/bin/env python
print "My Script is running"
import os
if os.path.exists("/tmp"):
def myfunc():
x = 4
return x
class Foo(object):
y = 1

f = Foo()
print f.y + myfunc()





6. Abuse conditional logic to the point that you double or even triple an "unmaintainable" Cyclomatic Complexity Score of 50.

Nothing says I suck at Python better, then writing nested if/else statements from here to the moon. How you can tell you sucked enough? Easy, just run the cyclomatic complexity metric from PyMetrics, and if your function or method doesn't yet rate a 50, which is basically unmaintainable/untestable code, then keep trying! If you can double or even triple that to say 100 or 150, you will put the capital "S" in Suck!


7. Use sleep statements like Holy Water.

If you write something sketchy and want some extra "luck", then sprinkle in a few time.sleep statements. If you use them randomly and arbitrarily it will get the point across in short order, that you don't know what the hell that piece of code does and you're just guessing! Awesome!

8. Initiate the same logic more then once, "just to be sure".

Often when you're writing some really crappy code, you're lucky if you know what it is doing. If you can write a function that does something that makes you feel emotionally safe and then call it for luck a few times...bingo...you win!
Something like this is always a gold standard:



count = 0
for i in range(5):
if os.path.exists("/tmp"):
print "bingo"

def foo():
print "stuff"

if os.path.exists("/tmp"):
import sys
sys.exit(1)





9. Write Library Code that does a sys.exit(0) on an exception.

If you can write an API that catches all exceptions and then does a silent sys.exit(0), you will really piss someone off that uses you're code and demonstrate you're a hack.

Something like this is a good start:




def api_entry_point():
try:
obj.method()
except:
#lets not bother the developer with this exception. He should quit out immediately!
import sys
sys.exit(0)



10. Reimplement the Python Standard Library in every piece of code you write.

Show you really don't give a rat's ass about learning the language. Reimplement arg parsing,
config parsing, the subprocess module and more.

Summary

If you can do just a couple of these things in every piece of code you write, you are well on your way to writing bad python code! Stay tuned for part II.

Wednesday, August 19, 2009

Adapt Is Now Using Bobo

The trunk version of Adapt, a commandline tool/logic router to WSGI web app framework I am developing is now using Bobo for the abstraction piece on top of WebOb.

If you haven't checked out Bobo or WebOb and you develop Python web apps, your missing out. Wow, great stuff Jim and Ian!

Sunday, May 3, 2009

AIPY SIG 05/03/2009: Statistics Versus Logic

On the Python Artificial Intelligence SIG, the topic of the week was statistics versus logic.

Graham Higgins dropped quite a few links:

[1] http://languagelog.ldc.upenn.edu/nll/?p=1374
[2] http://en.wikipedia.org/wiki/Conditional_entropy
[3] http://www.safarmer.com/fsw2.pdf
[4] http://www.cs.washington.edu/homes/rao/ScienceIndus.pdf
[5] http://homepages.inf.ed.ac.uk/s0450736/maxent_toolkit.html
[6] http://r.research.att.com/tools/
[7] http://www.amazon.com/Gods-Demons-Symbols-Ancient-Mesopotamia/dp/0292...
[8] http://www.prehistory.it/ftp/winn.htm
[9] http://www.flonnet.com/fl1801/18010730.htm
[10] http://blog.wired.com/wiredscience/2009/04/indusscript.html
[11] http://www.newscientist.com/article/dn17012-scholars-at-odds-over-mysterious-indus-script.html
[12] http://www.acl-ijcnlp-2009.org/main/acceptedfullpapers.html

Rick Thomas responded back with:

http://code.google.com/p/pebl-project/
http://code.google.com/p/python-dlp/
http://www.betaversion.org/~stefano/linotype/news/275/
http://ite.gmu.edu/~klaskey/papers/Costa_Laskey_MEBN_wo_Tears.pdf

AIPY Mailing List: http://groups.google.com/group/aipy?hl=en

Tuesday, April 28, 2009

Python Functional Programming Antipatterns: When Closures Can Be A Solution In Search of A Problem (PART 1)

One of the things I don't like about closures [1](via nested functions) is how they obscure intent in code. For example, if you just want to retain state why use a closure if you could just use a class? Sure a closure sounds cooler, but a class or a regular group of functions is often more flexible and readable than a closure.


Example 1: Simple Persistent State
Closure That Stores State: (1A)



In [39]: def outer():
....: x = 1
....: def inner():
....: return x
....: return inner
....:

In [40]: func = outer()

In [41]: func
Out[41]:

In [42]: func()
Out[42]: 1



Class That Stores State (1B)



In [46]: class State(object):
....: def __init__(self):
....: self.x = 1
....: def func(self):
....: return self.x
....:
....:

In [47]: func = State().func

In [48]: func()
Out[48]: 1





Score: +1 Class
Summary: If you simply want to persistent state, why use a closure that
has an odd signature, when you can simple use a class?


Example 2: Flat is better than nested, closures taken to an extreme with multiple nesting

Nested function w/ function that operates on state (2A)




In [18]: def way_outer():
....: wo = 1
....: def inner():
....: i = 2
....: def way_inner():
....: return i + wo
....: return way_inner
....: return inner
....:

In [19]: out = way
way_inner way_outer

In [19]: out = way_outer()

In [20]: out
Out[20]:

In [21]: out()
Out[21]:

In [22]: way_way_out = out()

In [23]: way_way_out()
Out[23]: 3



Class functions that operate on state (2B)



In [24]: class Addition(object):
....: def __init__(self):
....: self.x = 1
....: self.y = 2
....: def add(self):
....: return self.x + self.y
....:
....:

In [25]: a = Addition().add

In [26]: a
Out[26]: [bound method Addition.add of __main__.Addition object at 0x78db70]

In [27]: a()
Out[27]: 3




Score: +2 Class
Summary: You might be thinking "duh" with this example, but yes, that is exactly the point! Why nest things if you don't have to? Especially because of the fact that if someone looks at your highly nested closure they will go WTF as they should. Why make things more complex then they need to be? Just because you can use closures doesn't mean you should or it makes your code intuitive and readable.

Example 3: Delaying Execution of a Function
Delayed execution of a function using closures (3A)



In [29]: def outer():
....: def inner(x):
....: return x + 1
....: return inner
....:

In [30]: func = outer()

In [31]: func(3)
Out[31]: 4



Delayed execution of a function using class: Example (3B)


In [1]: class DelayCall(object):
...: def __init__(self, x):
...: self.x = x
...: def logic(self):
...: return self.x + 1
...: def delay(self):
...: return self.logic
...:
...:

In [3]: d = DelayCall(3)

In [4]: func = d.delay()

In [5]: func()
Out[5]: 4




Delayed execution of a function that takes args using a lambda in a class: Example (3C)


In [19]: class LambdaDelayCall(object):
....: def logic(self, x):
....: return x + 1
....: def delay(self):
....: return (lambda x: self.logic(x))
....:
....:

In [20]: l = LambdaDelayCall()

In [21]: func = l.delay()

In [22]: func(5)
Out[22]: 6



Delayed execution of a function that takes args using a lambda in a class w/ __call__: Example (3D)


n [19]: class LambdaDelayCall(object):
....: def logic(self, x):
....: return x + 1
....: def __call__(self):
....: return (lambda x: self.logic(x))
....:
....:

In [37]: l = LambdaDelayCall()

In [40]: func = l()

In [41]: func(3)
Out[41]: 4





Score: +3 Class
Summary: While 3A is shorter, I think it is much less clear then 3B, 3C or 3D, the class examples. I think of a closure in terms of an outer function that needs to operate on an inner function, such as in the case of a decorator. Using a closure just to delay execution of a function doesn't seem right to me, and I feel like it obscures the code.

Conclusion:

Closures are useful when you want to modify the state of inner function and return, as in the case of decorators. Lambdas, from Learning Python 3rd edition, " are often used as a way to inline a function definition, or to defer execution of a piece of code.". While closures are useful and powerful, with power comes responsibility. [1] Nested functions aren't that clear, try a class or maybe you don't even need a closure?. Make sure you Python for good, not evil. Stay tuned for the next installment.

[1] Added note about "nested functions" 04/29/2009


References:
Bruce Eckel on Decorators
Zen of Python
Functools Partial
Dive Into Python: Lambda

Sunday, April 26, 2009

Python Artificial Intelligence SIG Weekly Update: 04/26/2009

I am going to attempt to do weekly updates based on the newly formed Python AI SIG, http://groups.google.com/group/aipy . Sunday, New Zealand time, is going to be my day to summarize what is going on.

So far the hot topics are as follows:

1. Getting a code repository setup somewhere to share ideas.
2. Getting some domain setup so we can share and categorize what we learn. Jeff Rush mentioned possibly ai.python.org and using Sphinx. I kind of like that idea.
3. Filtered RSS reader: It seems like getting a bot to pre-filter RSS is low hanging fruit.
4. Continuous monitoring of the body: We are discussing the feasibility of continuous monitoring of the body, one gotcha so far is what device do we use?

Tuesday, April 21, 2009

An "Adaptable" Commandline Tool and Web Service Generator

I have been hacking on a Commandline tool and Web Service Generation framework called Adapt. Last night, Adam Shand, and I hacked on getting Phase 2 together, which is making a web service automatically serve out the same URLs as a commandline tool options, which are defined in a config file.

The not even Alpha quality code is here: http://bitbucket.org/noahgift/adapt/

The basic problems I am trying to solve is this:

1. Automatically convert existing Python command line tools into Web Services.
2. Create a plug and play WSGI application so I can talk to other WSGI goodies like LDAP auth, debugging, etc.
3. Create Yet Another Web Framework in Python (although it is pretty unconventional)
4. Automatically adapt existing shell scripts, aliases and Python scripts into a dynamically created command line tool.
5. Declarative mapping of actions via a simple config file.
6. Let people that are completely ignorant of Python, create command line tools and web services by running a tool.
7. Let people do BOTH, in one step.

Is this crazy...yes. But, it is also fun. Once I complete code coverage to 100% and move common code into a library, and make some "frameworkish" code, I will release it. Feel free to help if you think this sounds fun too.


I named it after my blog post "Adapt or Die". Because it was a direct outshoot of my philosophy on tools.

Thursday, April 9, 2009

Python Artificial Intelligence Special Interest Group Mailing List

From the title of my blog,"Artificial Code", you can tell I am interested in Artificial Intelligence. I have noticed quite a few people in the Python community are interested in AI, so wondered if there was a mailing list, evidenced by viewing Raymond's AI talk at PyCon, and a recent blog post by Tennessee, and even Guido himself :). My google searches revealed there wasn't, so I started one:

http://groups.google.com/group/aipy

I think it would be fun to share ideas about artificial intelligence and then make real world implementations. We can also share how everything thinks that people interested in AI are crazy and that it is an unsolvable problem :) If you are interested in both AI and writing Python implementations, then join the list, and let's get to work.

Some of the things I am interested in are solving "low hanging fruit" problems that can be done this year, or sooner.