Define a method outside of class definition?

PythonClassMethods

Python Problem Overview


class MyClass:
	def myFunc(self):
		pass

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

Python Solutions


Solution 1 - Python

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.

Solution 2 - Python

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...

Solution 3 - Python

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)

Solution 4 - Python

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

Solution 5 - Python

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),

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser975135View Question on Stackoverflow
Solution 1 - PythonWeebleView Answer on Stackoverflow
Solution 2 - PythonewellingerView Answer on Stackoverflow
Solution 3 - PythonMatt AlcockView Answer on Stackoverflow
Solution 4 - PythonaweisView Answer on Stackoverflow
Solution 5 - PythonBoyce CecilView Answer on Stackoverflow