Skip to content

Instantly share code, notes, and snippets.

@ZoomQuiet
Forked from MineRobber9000/donotuse3.py
Created September 24, 2020 02:04
Show Gist options
  • Save ZoomQuiet/40f14760d5e7378ec380e3468e30d71d to your computer and use it in GitHub Desktop.
Save ZoomQuiet/40f14760d5e7378ec380e3468e30d71d to your computer and use it in GitHub Desktop.
How to NEVER use lambdas - Python 3 edition
###########################################################
# How to NEVER use lambdas. An inneficient and yet educa- #
# tonal [sic] guide to the proper misuse of the lambda #
# construct in Python 3.x. [DO NOT USE ANY OF THIS EVER] #
# original by (and apologies to): e000 (13/6/11) #
# now in Python 3 courtesy of: khuxkm (17/9/20) #
###########################################################
## Part 1. Basic LAMBDA Introduction ##
# If you're reading this, you've probably already read e000's
# original, but in case you didn't read that one back when it
# was big, I should explain what lambdas are. As per e000:
# (quote)
# Lambdas are pretty much anonymous "one line" functions
# that are able to be constructed at runtime. Typical usage
# would be to plug it into `filter()` or `map()`, but that's
# boring. Let's start with the most basic of basic examples.
# (endquote)
def pow(x, power):
return x**power
# Simple enough, just a function that raises `x` to the `power`
# power. Now let's do it in lambda form:
pow = lambda x, power: x**power
# Easy.
## Part 2. Scoping within Lambdas ##
# Again, this part should be familiar to you if you read the
# original by e000. Nothing changed in Python 3, so I'll just
# quote the explanation here: (quote)
# Let's try something a bit more complicated. A random
# string or password generator? Sure.
import random, string
characters = string.digits + string.letters
def randomPasswordGenerator(length):
return ''.join(random.choice(characters) for i in range(length))
# >>> randomPasswordGenerator(8)
# 'bDpHVxiO'
# Haah! That was cake! Now in this terrible tutorial, we're going to
# prohibit the use of defining ANYTHING outside of the lambda function,
# including any kind of variable, or import. So, how are we going to get
# `random` and `string`. Well the answer is obvious, we're going to make
# a lambda inside of a lambda inside of a lambda. We're also going to use
# a bit of `__import__` trickery.
# (endquote)
# The import trickery remains the same. Like I said, nothing really
# changed in Python 3 to break this example. As such, I even copied the
# source directly from donotuse.py (changing `xrange` to `range` as the
# former no longer exists).
randomPasswordGenerator = \
(lambda random, string: # level 1
(lambda characters: # level 2
lambda length: ''.join(random.choice(characters) for i in range(length)) # level 3
)(string.digits + string.letters) # level 2 args
)(
__import__('random'), # level 1 args
__import__('string')
)
# That's... unpythonic, disgusting, an abomination, and some might even
# call it ungodly. Why would anyone do that to themselves?
# One word: masochists.
## Part 3. Giving lambdas function names ##
# This is the first semi-new part. I'll quote e000 until there's new info.
# (quote)
# In a world where absurdity peaks, and somehow we NEED a
# function name, for what ever reason. Here's how to do it.
# THIS IS NOT FOR THE WEAK HEARTED.
# First, let's start with some regular code.
def myFunc(a, b):
return a + b
# >>> myFunc
# <function myFunc at 0x...>
myLambda = lambda a, b: a + b
# >>> myLambda
# <function <lambda> at 0x...>
# Uh'oh! How are we going to give this function a name?
# (endquote)
# In Python 2, we could use `new.function`. But in Python 3, `new` was
# replaced with `types`. Somehow, the new way to do it is even worse.
myFunc = (lambda types:
types.FunctionType((lambda a, b: a + b).__code__.replace(co_name="myFunc"),{},"myFunc")
)(__import__("types"))
# >>> myFunc
# <function myFunc at 0x...>
# In the immortal words of e000, "LOL! It works! Isn't that disgusting?"
## Part 4. A class? In my lambda? It's more likely than you may think. ##
# Let's start with a simple class. I'll write my own example this time. How
# about a simple namespace?
class Namespace:
def __init__(self,**kwargs):
self.__dict__.update(kwargs)
def __repr__(self):
keys = sorted(self.__dict__)
items = ("{}={!r}".format(k,self.__dict__[k]) for k in keys)
return "{}({})".format(type(self).__name__,", ".join(items))
def __eq__(self,other):
return other.__dict__==self.__dict__
# Yes, I know that's basically just types.SimpleNamespace, but shush. Let's
# lambda-ify it. Instead of `new.classobj`, we have `types.new_class`.
Namespace = (lambda types:
types.new_class("Namespace",(),exec_body=(lambda ns: ns.update(
dict(
__init__=(lambda self,**kwargs: self.__dict__.update(kwargs)),
__repr__=(lambda self: "{}({})".format(type(self).__name__,", ".join("{}={!r}".format(k,self.__dict__[k]) for k in sorted(self.__dict__)))),
__eq__=(lambda self, other: self.__dict__==other.__dict__)
)
)))
)(__import__("types"))
# >>> Namespace(x=3,s="Hello world!")
# Namespace(s='Hello world!', x=3)
# Holy mother of pearl, that is an abomination.
## Part 5. Flask + Lambdas = Even More of An Abomination ##
# This is as far as I'll go (mainly because I don't know how to Twisted).
# If you want to go even deeper, use the dark arts I've already taught you
# to convert Parts 6a and 6b into Python 3.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "Hello, world!"
app.run()
# And that becomes...
(lambda flask:
(lambda app:
(app,
app.route('/')(lambda: 'Hello, world!')
)[0]
)(flask.Flask(__name__)).run()
)(__import__("flask"))
# What a disaster.
## Part 5b. I Lied, This Is Worse ##
# No comment.
from flask import Flask, redirect
shortnames = {"google":"https://google.com/","khuxkm":"https://khuxkm.tilde.team","*":"https://example.com"}
app = Flask(__name__)
@app.route('/')
def index():
return redirect(shortnames.get("default","https://example.com"),code=307)
@app.route('/<path:short>')
def route(short):
return redirect(shortnames.get(short,shortnames.get("default","https://example.com")),code=307)
app.run()
# Pulling out all of the stops here...
(lambda flask, flaskviews, types, shortnames:
(lambda lmb2view:
(lambda app, index, route:
(app,
app.route("/")(index),
app.route("/<path:short>")(route)
)[0]
)(flask.Flask(__name__),
lmb2view(lambda s: flask.redirect(shortnames.get("default","https://example.com"),code=307),"index"),
lmb2view(lambda s,short: flask.redirect(shortnames.get(short,shortnames.get("default","https://example.com")),code=307),"route")).run()
)(lambda lmb,name: types.new_class(name,(flaskviews.views.View,),{},(lambda ns: ns.update(dict(dispatch_request=lmb)))).as_view(name))
)(__import__("flask"),__import__("flask.views"),__import__("types"),
{
"google":"https://google.com/",
"khuxkm":"https://khuxkm.tilde.team",
"*":"https://example.com"
})
# What? Just... what? It's so goddamn big it barely fits on my 151-column monitor, it breaks all
# sorts of Zen, and I should probably be executed for crimes against humanity, but it's a URL
# shortener implemented entirely in lambdas.
# You ever write completely morally sound code that still leaves you feeling dirty afterwards?
# Me too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment