5

It's possible to define a class without using the class keyword.
The following ...

get_i = lambda self: self.i    
get_i.__name__ = 'get_i'
get_i.__qualname__ = 'Klass2.get_i'
dct = dict(a=1, i=4, get_i=get_i)    
Klass2 = type('Klass2', (SuperK,), dct)

... produces the same end result as:

class Klass1(SuperK):
    a = 1
    i = 4
    def get_i(self):
        return self.i

How can we do something similar for functions? That is, how can we define a function without using the def or lambda keywords? What might a pure-python implementation of dehf look like if the following two pieces of code created identical foos?

def foo(bar):
    bar += 934
    return bar

foo = dehf(blah, blah, blah, blah, [...])
Toothpick Anemone
  • 4,290
  • 2
  • 20
  • 42
  • 1
    You used `lambda` to define the function in the class. Why do you think you can define a function without `lambda`? – Barmar Apr 06 '18 at 21:55
  • The use cases for creating a class with `type` are rather rare (like meta-classes). but why would you want to create a function without `def` or `lambda`? – Chris_Rands Apr 06 '18 at 22:06
  • Well I suppose if you want to make your code unmaintanable this might be a good idea. But IRL what good reason might you have to want to use such obtuse ways of defining a class or a function? – DisappointedByUnaccountableMod Apr 07 '18 at 00:04
  • @Chris_Rands @barny One use-case is to create functions at with run-time-generated names. For example, suppose we want to create a function named `baz` at runtime, but we don't know that its going to be named `baz` when we write our code. As such, we can't simply write `def baz(*args):`. Maybe there's a decorator which outputs a function named, "`pretty_`<`foo`>," where is the function passed into the decorator. You can write, `func.__name__ = "pretty_" + foo.__name__`, but there are other use-cases for constructing functions without the `def`-keyword which aren't as easily dealt with. – Toothpick Anemone Apr 22 '18 at 02:01
  • If your question is about creating function names dynamically, then ask that question instead, you can still use `def` e.g. https://stackoverflow.com/questions/13184281/python-dynamic-function-creation-with-custom-names Currently it feels like an XY problem – Chris_Rands Apr 22 '18 at 06:53

1 Answers1

6

You can create functions by calling the types.FunctionType constructor. Keep in mind however that this constructor is undocumented and implementation specific. In CPython, we can figure out the constructor arguments by calling help(types.FunctionType):

class function(object)
 |  function(code, globals[, name[, argdefs[, closure]]])
 |  
 |  Create a function object from a code object and a dictionary.
 |  The optional name string overrides the name from the code object.
 |  The optional argdefs tuple specifies the default argument values.
 |  The optional closure tuple supplies the bindings for free variables.

To create a code object, we can use compile:

code = compile('print(5)', 'foo.py', 'exec')
function = types.FunctionType(code, globals())

function()  # output: 5
Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
  • 1
    Interesting, but does this not feel like an XY problem, why would you do this? – Chris_Rands Apr 06 '18 at 22:08
  • 1
    @Chris_Rands No idea, you'd have to ask the OP. Maybe it's just simple curiosity :) – Aran-Fey Apr 06 '18 at 22:17
  • I have a use case, kind of. I have a module where I generate a set of functions at module scope. It works fine, except it totally confuses the IDE and code validation tools. So I needed to add a stub for each of the functions, and those stubs can be represented more compactly with something like your example. – Roger Dahl Jan 21 '19 at 05:42