Is it possible to have a function run at the beginning of every function of a class without explicitly writing it? I'm going to have a class with 20 or so methods, and though I can just copy and paste, I was wondering if there was an easier way to do things. Thanks in advance.

Member Avatar for masterofpuppets

hi,
well it depends on what you want to do, why don't you just define the function and then reuse it in the class methods. :)

I'm more interested in if said function can be added in theory to every single function in said class all in one go, rather than copying and pasting arbitraryFunction() 20 or so times.

Yes, you can, although its not that pretty, here is something that i think shows how something like that can be done.

class Example(object):
    #This is what we use to call every function
    def functionCaller(self, functionName):
        #This is the function that needs to 
        #be called every time
        self.FunctionThatGetsCalledFirst()
        #Now we call the function that was supplied
        exec("self."+functionName+"()")

    def FunctionThatGetsCalledFirst(self):
	print "First"
	
    def Test(self):
        print "Hello"

        
e =Example()
#Try and call the function Test()
e.functionCaller("Test")
"""
First
Hello
""""

Hope that helps :)

Try using decorators.

They are a language feature in at least Python 3.0 that perform code on a function or method defined after them. Optionally, they can return a new function that will be assigned to the newly defined function. There are function decorators and class decorators. I haven't studied them in depth, so I could be wrong about some things or there could be more to them, but they seem to be a solution to your problem.

Here's the code using a function decorator in case I wanted "Hello, world!" printed whenever one of my functions is called.

def say_hello(function):
    def new_function():
        print("Hello, world!")
        function()
    return new_function

@say_hello
def myfunc():
    print("This is my function.")

@say_hello
def mysecondfunc():
    print("This is my second function.")

myfunc()
mysecondfunc()

The resulting output should be:

Hello, world!
This is my function.
Hello, world!
This is my second function.

The first function is the decorator. It takes only one argument, the function it is to modify or use.

The "@say_hello" is the decorator syntax. It indicates to the interpreter which function or class I want to call to use or modify the function.

Inside the first function, it defines a new function that prints "Hello, world!" and executes the function it took as an argument. I should mention that I think that if it is used on functions with arguments, this new function definition should accept *args and **kwargs in order to support your function arguments.

Then I define my own two functions that print which function they are, and then I call those functions.

Research Python decorators if you're interested in learning more.

mmmm, i would use decorators as well... i was just thinking if you didnt want to have to type that arbitraryFunction() that you probably wouldn't want to type @arbitraryDecorator That being said, decorators can be very useful and powerful especially when it comes to classes, so if you haven't used them before i would think its probably a good idea to have a go, even if it just is to lean about them. :)

mmmm, i would use decorators as well... i was just thinking if you didnt want to have to type that arbitraryFunction() that you probably wouldn't want to type @arbitraryDecorator

I didn't catch that reply.

If you used decorators you would have to copy and paste the decorator for each method. I can understand the problem there.

The more interesting trick would be to create a decorator that could handle each and every method in a class as per the user's specifications.

I think it might be possible. I tested some code and I discovered that a decorator can also be applied to a class.

Now what I was thinking is that this decorator could loop through each callable name in the class dictionary and then manipulate this name the way a normal decorator does. It might be simple for a basic class, but a problem that occurred to me was if the class inherits other classes, and also the issue of method resolution order.

It was a ***** to do, but I believe I figured out how to decorate each and every method in a class by decorating only the class itself.

def method_decorator(class_declaration):
    class NewClass():
        pass
    for key in class_declaration.__dict__:
        if hasattr(class_declaration.__dict__[key], '__call__'):
            def new_method(*args, **kwargs):
                print("This is a decorator.") #Replace this with your code.
                class_declaration.__dict__[key](*args, **kwargs)
            setattr(NewClass, str(key), new_method)
    return NewClass

@method_decorator
class MyClass(object):

    def __init__(self):
        print("This is my class.")

    def method(self):
        print("This is my method.")

x = MyClass()
x.method()
commented: A class decorator is the solution. +2

Actually, this code is wrong. I retested it, and I noticed an error. This code when run prints "This is my class both times."

I'll get to the bottom of it.

P.S. I realize what it is. The new_method definition doesn't create a new function each time it is called, its name is merely rebound to the new function.

cud someone plz help:
In semantic computing when we add functions and classes to the database of GNOWSYS, why is it that we create a class for every function?

commented: Make a new thread +0
def decorator(function):
    def wrapped(*args,**keywargs):
        print("Decorated")
    return wrapped

class MyMetaClass(type):
    def __new__(meta,classname,bases,classDict):
        for name,item in classDict.items():
            if hasattr(item,"__call__"):
                classDict[name] = decorator(item)
        return type.__new__(meta,classname,bases,classDict)


class MyClass(object):
    __metaclass__ = MyMetaClass
    def __init__(self):
        print("This is my class.")
    def method(self):
        print("This is my method.")

x = MyClass()

x.method()

That's how I would do it.
It's considered black magic, though. I hate that kind of evil code.

Also, this is not my code.
It is adapted from Michael Foord's, the master of IronPython, someone whose coding expertise towers above mine.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.