在类定义之外定义一个方法?

Posted

技术标签:

【中文标题】在类定义之外定义一个方法?【英文标题】:Define a method outside of class definition? 【发布时间】:2012-03-16 08:11:14 【问题描述】:
class MyClass:
    def myFunc(self):
        pass

我可以在类定义之外创建MyFunc(),甚至可以在另一个模块中创建吗?

【问题讨论】:

是的……您可以(几乎)在您想要的地方定义一个函数,但目的是什么?你想达到什么目标?请注意,类中的函数与外部的函数不同,例如,使用 self 参数,它引用创建函数的实例 功能实在是太多了。并且允许用户添加更多。 “类”基本上是有用的辅助函数的容器。 听起来您正在使用继承,其中一个类包含“帮助器”函数列表。然后另一个类可以实现这个类并使用它的功能! 我可能在这里错误地使用了“帮助者”这个词。我的意思是该类包含在其他地方使用的各种功能。所以它基本上是用于各种任务的“全局”函数的容器。 该类与需要访问这些函数的类继承的类有什么区别?是因为类包含共享资源吗?你有类似单身的课程吗? 【参考方案1】:

是的。您可以在类之外定义一个函数,然后在类主体中将其用作方法:

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

class MyClass:
    myMethod = func

你也可以在类定义后添加一个函数:

class MyClass:
    pass

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

MyClass.myMethod = func

如果需要,您可以在不同的模块中定义函数和类,但我建议不要在一个模块中定义类,然后将其导入另一个模块并动态添加方法(如我的第二个示例),因为那么根据是否导入了另一个模块,您的行为与该类的行为会令人惊讶地不同。

我要指出,虽然这在 Python 中是可能的,但它有点不寻常。您在评论中提到“允许用户添加更多”方法。这听起来很奇怪。如果您正在编写一个库,您可能不希望库的用户动态地将方法添加到库中的类。库的用户创建自己的继承自您的类的子类比直接更改您的子类更正常。

我还要提醒一下,函数根本不必在类中。 Python 不像 Java 或 C#,你可以只拥有不属于任何类的函数。如果你想将函数组合在一起,你可以把它们放在同一个模块中,你可以将模块嵌套在包中。仅在需要创建新数据类型时才使用类,而不仅仅是将函数组合在一起。

【讨论】:

在声明函数后,是否有更短的方法可以将函数添加到类中?因为它似乎并不比在其中定义它更简单/更干净(不是我知道它应该是) 当然,如果您希望它干净简单,只需在类中声明即可。在定义类之后添加函数的能力相当深奥,并且可能主要用于出于某种原因需要在运行时创建全新类的高级情况。您能否更好地描述您正在尝试做什么:为什么您的类有这么多大方法,您想将它们放在单独的文件中? 忘记“其他模块”的事情。我想让它们超出实际的类定义的主要原因是不必全部缩进(大约 80 个)。我认为那是“更清洁”。否则,在一个模块中只包含函数似乎比创建一个包含 80 个函数的类更简洁。 对修改 Python 记录器非常有用,例如添加新的日志记录级别。 更好的解决方案(视情况而定)可能是使用 types.MethodType。信用和信息在这里:tryolabs.com/blog/2013/07/05/run-time-method-patching-python【参考方案2】:

您可以在类之外定义一个函数,然后添加它。但是,将函数分配给类或实例对象存在细微差别。这是一个例子:

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

让我们先看看MyClass1 中发生了什么。此类中的foobar 类似于普通方法,就好像它是在类定义中定义的(即,它是绑定到此类实例的方法)。让我们看看这是什么样子的……

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"

这与MyClass2 有何不同?在MyClass2 中,foobar 只是对 bar 函数的引用,而不是绑定方法。因此,我们必须传入实例才能使该函数正常工作。例如

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"

虽然我不确定这样做是否是一种好习惯......

【讨论】:

【参考方案3】:

是的,你绝对可以在类之外拥有函数。这是一个小例子...

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)

【讨论】:

不,我的意思是我可以在类之外定义一个类的方法吗?【参考方案4】:

我对你正在寻找的东西进行了拍摄,其中一个类 Helper 为一个专门的类 (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()

这将打印出来

>>> 2

【讨论】:

【参考方案5】:

你可以! 例如: 在 django 中,这是视图函数,它只保留在我的应用程序的视图模块中

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

在 url 路由模块中,我只是从模块中导入它并使用它,没有任何类

from . import views
from django.urls import path
urlpatterns = [
    # homepage of app
    path('', views.user_list_view),

【讨论】:

以上是关于在类定义之外定义一个方法?的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用 MooseX::Declare 在类之外定义函数吗?

我可以在类之外定义私有模板函数吗?

无法在类之外定义类函数

在类方法内部访问类的命名空间之外?

C++静态成员变量必须在类的定义之外进行声明 (error LNK2001: unresolved external symbol)

C++静态成员变量必须在类的定义之外进行声明 (error LNK2001: unresolved external symbol)