不触发__init__的情况下调用类函数

9

有没有办法在不触发类的__init__部分的情况下调用类内部的函数?假设我有如下类,通常我会这样调用函数:

class Potato():
    def __init__(self):
        print("Initializing")
    def myfunction(self):
        print("I do something")

Potato().myfunction()

但是正如预期的那样,它打印了初始化部分。 现在,如果我想在不触发它的情况下调用myfunction。 你会怎么做? 这样做的优缺点是什么? 这是可能的吗?


那就不要使用__init__。在该示例中,您根本没有初始化任何变量。 - Wright
那只是一个例子,我想知道如果真正的代码中有变量但我在调用函数时不想调用它们会发生什么。或者这是否可能。 - Saelyth
你不会“调用”变量。__init__是“初始化”的意思。这意味着,一旦你实例化一个类,该特定实例就会获得你初始化为属性的任何变量。我不知道你所说的“在调用函数时不调用它们”的意思。 - Wright
抱歉造成困惑,英语不是我的母语。我只是想知道在实例化类时是否有一种方法可以排除类的__init__函数。希望这样更有意义。@Trauer 可能吧,我正在学习类及其工作原理,然后遇到了这个问题。我知道有更好的调用函数的方法,但我只是想满足我的好奇心,“这样做可能吗?” - Saelyth
你可以创建一个子类,覆盖__init__方法并什么也不做...虽然不确定这样做的意义何在。 - kindall
4个回答

18

我不确定这是否符合你的要求,但是:

classmethod 或者 staticmethod 可以在不创建类实例的情况下使用 - 这意味着 init 不会被调用:

class MyClass:
   def __init__(self):
      print("Initialize instance - not used")

   @staticmethod
   def my_static(toprint):
       print(toprint)

MyClass.my_static("Print this")

可能是这样,能否解释一下? - Saelyth
我添加了一个示例来演示静态方法的使用。 - DonGru
2
这是我会选择的路径。我不知道为什么你要使用被接受的答案。 - Cory Madden
哦,那是新手失败:我实际上做了两个答案。第一个是关于是否可能不初始化__init__,所以我接受了这个答案,因为我必须知道类在这方面的能力,并且这得到了很好的解决。然后,另一个问题是如何在不初始化类的情况下调用其中的方法,在这方面我同意这是很好知道的。 - Saelyth
昨天我真的那么愚蠢吗?有两个问题,不是答案。 - Saelyth

13

是的,这是可能的。

使用辅助函数

您可以编写一个辅助函数,将您的类的__init__方法替换为虚拟方法,然后实例化该类,之后再将旧的__init__重新赋回给类。

def skip_init(cls):
    actual_init = cls.__init__
    cls.__init__ = lambda *args, **kwargs: None
    instance = cls()
    cls.__init__ = actual_init
    return instance

演示:

>>> a = skip_init(Potato)
>>> a.myfunction()
I do something

覆盖__new__

您可以覆盖类的__new__方法,并基于参数替换__init__为一个虚拟方法。

def new_init(cls, init):
    def reset_init(*args, **kwargs):
        cls.__init__ = init
    return reset_init


class Potato():
    def __new__(cls, *args, **kwargs):
        instance = object.__new__(cls)
        lazy = kwargs.pop('_no_init', False)
        if not lazy:
            return instance
        cls.__init__ = new_init(cls, cls.__init__)
        return instance

    def __init__(self):
        print("Initializing")

    def myfunction(self):
        print("I do something")

示例:

>>> a  = Potato(_no_init=True)
>>> a.myfunction()
I do something
>>> b  = Potato()
Initializing
>>> b.myfunction()
I do something

这正是我所需要知道的,如果有可能的话。谢谢您。 - Saelyth
1
@Saelyth 很高兴能够帮到您。我还提供了另外一种可能会对您有用的方法。 - Ashwini Chaudhary
1
很棒的解决方案! - Nikolay Shindarov

1
我知道这篇文章发表已经有一段时间了,但是值得一提的是,一个没有"self"的类方法可以在不调用构造函数(使用()和没有init)的情况下被调用。虽然并没有添加任何新内容,但我认为这简单地回答了这个问题。
>>> class Yolo:
...     def notify(data):
...         print(f"some data: {data}")
...
>>>
>>> Yolo.notify({1:1})
some data: {1: 1}
>>>

并且

>>> class Yolo:
...     @staticmethod
...     def notify(data):
...         print(f"some data: {data}")
...
>>> Yolo.notify({1:1})
some data: {1: 1}

与之相比,
>>> class Yolo:
...    def __init__(self):
...       print("init")
...    def notify(data):
...       print(f"some data: {data}")
...
>>>
>>> Yolo.notify({1:1})
some data: {1:1}
>>> Yolo()
init

0
1)你可以创建一个没有< strong>init的类,但它会更像一个函数。
2)如果你使用< code>__init__方法,那么每次调用类时都会被调用,但你可以避免触发变量(如果你选择这样做)。请注意,该方法仍然会被调用。
class Potato():
    def __init__(self,init_or_dont=1):
        self.init_or_dont = init_or_dont
        if self.init_or_dont:
            print("Initializing")
    def myfunction(self):
        print("I do something")


Potato(init_or_dont=0).myfunction()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接