99
class MyClass:
    def myFunc(self):
        pass

Can I create MyFunc() outside of the class definition, maybe even in another module?

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 2
    Yes... you can define a function where you want (almost), but for what purpose? What do you want to achieve? Note that a function in a class is different from the one outside, e.g., the use of the self parameter, which reference the instance the function is created in – aweis Feb 26 '12 at 17:05
  • The functions are just too much. And users are allowed to add more. The "class" is basically a container of useful helper functions. –  Feb 26 '12 at 17:07
  • It sounds like you are working with inheritance, where one class contains a list of "helper" function. Then another class can implement this class and use the functions from it! – aweis Feb 26 '12 at 17:09
  • I might have used the term "helper" wrongly here. I mean the class contains various functions which are used everywhere else. So it's basically a container for "global" functions used for a wide variety of tasks. –  Feb 26 '12 at 18:07
  • And what is difference from that class and a class that is inherited by the class that needs access to thous functions? Is it because the class contains shared resources? Are you having a singleton-like class? – aweis Feb 26 '12 at 18:15
  • I never mentioned that the class should be inherited. Yeah, I suppose it's a singleton. Now it's a module I use for functions which do not fit eleswhere (in other classes), but think a class which always has that extra scope is better. –  Feb 26 '12 at 18:21
  • If you need extra scope, just add a submodule. Why do you need a class if you just want a collection of functions? It sounds like all your "class" methods would be static anyway. – snapshoe Feb 26 '12 at 20:45
  • If you just want to collect a bunch of loosely related functions that don't operate on shared state, a module is definitely more appropriate than a class. – Weeble Feb 26 '12 at 20:48
  • Yeah, but it's harder to prevent people from using "from import *" and getting 80 global functions. –  Feb 27 '12 at 10:40
  • This comes in handy when you define a class in python interpreter and want to add a method to it if you want to test something. – Lokesh Meher Dec 19 '16 at 07:34

5 Answers5

150

Yes. You can define a function outside of a class and then use it in the class body as a method:

def func(self):
    print("func")

class MyClass:
    myMethod = func

You can also add a function to a class after it has been defined:

class MyClass:
    pass

def func(self):
    print("func")

MyClass.myMethod = func

You can define the function and the class in different modules if you want, but I'd advise against defining the class in one module then importing it in another and adding methods to it dynamically (as in my second example), because then you'd have surprisingly different behaviour from the class depending on whether or not another module has been imported.

I would point out that while this is possible in Python, it's a bit unusual. You mention in a comment that "users are allowed to add more" methods. That sounds odd. If you're writing a library you probably don't want users of the library to add methods dynamically to classes in the library. It's more normal for users of a library to create their own subclass that inherits from your class than to change yours directly.

I'd also add a reminder that functions don't have to be in classes at all. Python isn't like Java or C# and you can just have functions that aren't part of any class. If you want to group together functions you can just put them together in the same module, and you can nest modules inside packages. Only use classes when you need to create a new data type, not just to group functions together.

Weeble
  • 17,058
  • 3
  • 60
  • 75
  • Is there a shorter way to add a function to a class after it has been declared? Because it doesn't seem simpler/cleaner than just defining it inside it (not that I know it should be) –  Feb 26 '12 at 18:11
  • Certainly, if you want it to be clean and simple, just declare it inside the class. The ability to add a function after a class has been defined is rather esoteric, and probably mostly used in advanced situations that need to create entire new classes at runtime for some reason. Could you describe better what it is you're trying to do: why does your class have so many large methods that you want to put them in separate files? – Weeble Feb 26 '12 at 19:01
  • Forget about the 'other module' thing. The main reason I wanted to have them outside of the actual class definition was to not have to indent all of them (around 80). I thought that was "cleaner". Otherwise it seems cleaner to just have functions inside of a module than it is to create a class with 80 functions. –  Feb 26 '12 at 19:11
  • Really useful for modifying the Python logger, e.g. to add new logging levels. – Mad Physicist Sep 23 '16 at 19:46
  • 2
    Better solution(depending on the situation) could be using types.MethodType. credit and info here: https://tryolabs.com/blog/2013/07/05/run-time-method-patching-python/ – Cfir TSabari Mar 17 '19 at 09:13
  • What benefit would one get by defining the method outside the class but within the module? Also, what is such a function referred to in Python terminology? – AjB May 29 '23 at 07:05
  • @AjB I honestly can't think of one. This isn't really an extra feature that's been added to the language for this purpose - it's just a natural consequence of how classes are built in Python - the indented block of statements within the class is executed, and then the local variables it created are saved in the class's namespace where they become methods. – Weeble Jun 05 '23 at 21:41
11

You can define a function outside of a class and then add it. However, there is a subtle difference in assigning the function to the class or to the instance object. Here is an example:

class MyClass1(object):
    def __init__(self, bar):
        self.foo = 'up'
        MyClass1.foobar = bar

class MyClass2(object):
    def __init__(self, bar):
        self.foo = 'up'
        self.foobar = bar

def bar(self):
    return "What's " + self.foo

Let's first look at what is happening in MyClass1. foobar in this class is similar to a normal method as though it was defined inside the class definition (i.e. it is a method bound to the instance of this class). Let's take a look at what this looks like...

In [2]: x = MyClass1(bar)

In [3]: x.foobar
Out[3]: <bound method MyClass1.bar of <__main__.MyClass1 object at 0x104346990>>

In [4]: x.foobar()
Out[4]: "What's up"

How does this differ from MyClass2? In MyClass2, foobar is simply a reference to the bar function and is NOT a bound method. Because of this we must pass the instance in for this function to work properly. e.g.

In [5]: y = MyClass2(bar)

In [6]: y.foobar
Out[6]: <function __main__.bar>

In [7]: y.foobar()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-6feb04878e5f> in <module>()
----> 1 y.foobar()

TypeError: bar() takes exactly 1 argument (0 given)

In [8]: y.foobar(y)
Out[8]: "What's up"

Although I'm not sure if this is ever good practice to be doing it this way...

ikamen
  • 3,175
  • 1
  • 25
  • 47
ewellinger
  • 181
  • 1
  • 4
  • In class 2, should `self` get passed automatically when invoked via the instance? Am I missing something fundamental about Python here? – AjB May 29 '23 at 07:01
7

Yes you can definitely have functions outside of a class. Here is a mini example...

def date_parse(date_string):
  return date(date_string)


class MyClass:
   def myFunc(self):
       pass

   def myDateFunc(self, date_string):
      self.date = date_parse(date_string)
Vincent Savard
  • 34,979
  • 10
  • 68
  • 73
Matt Alcock
  • 12,399
  • 14
  • 45
  • 61
  • 1
    No, I mean can I define a method of a class outside of the class? –  Feb 26 '12 at 18:09
3

I give a shoot at what you are looking for, where one class Helper provides functions to a specialized class (MyClass)

class Helper(object):

    def add(self, a, b):
        return a + b

    def mul(self, a, b):
        return a * b


class MyClass(Helper):

    def __init__(self):
        Helper.__init__(self)
        print self.add(1, 1)


if __name__ == '__main__':
    obj = MyClass()

This will print

>>> 2
aweis
  • 5,350
  • 4
  • 30
  • 46
0

You can! For example: In django this is the view function and it just stay in the views module in my app

def user_list_view(request):
    queryset = User.objects.all()
    return render(request, 'list_user_users.html', {'object_list': queryset})

And in the url routing module I just import it from the module and use it there is no class whatsoever

from . import views
from django.urls import path
urlpatterns = [
    # homepage of app
    path('', views.user_list_view),
Boyce Cecil
  • 97
  • 2
  • 8