【问题标题】:In python3, what's the difference between defining a class method inside or outside __init__ function?在python3中,在__init__函数内部或外部定义类方法有什么区别?
【发布时间】:2020-11-24 14:57:52
【问题描述】:

例子

class Foo:
    def __init__(self, val):
        self.val = val
    def f(self,arg=None):
        if arg: print(arg)
        else: print(self.val)
    @classmethod
    def otherclassmethods(cls):pass

class Foo2:
    def __init__(self, val):
        # self.val = val, no need that
        def f(arg=val):
            print(arg)
        self.f = f
    @classmethod
    def otherclassmethods(cls):pass

我发现在__init__函数中定义一个类方法是完美的:

  1. 在普通的类方法中,我不再需要 self 参数了。
  2. Foo2不需要setattr,它是自动封装的。
  3. 函数看起来更类似于 c++。

如果我在__init__函数内部定义所有类成员,我更关心他们真正的实际效果。也许在概念上,__init__ 内部的闭包不是类方法,但我认为它作为类方法工作得很好。基于此,我的问题是:在__init__ 函数内部或外部定义类方法有什么区别?

请帮帮我。

【问题讨论】:

  • 在__init__ 内部,它不是一种方法。这只是一个本地函数。
  • @chepner 但我有self.f = f,它变成了一个闭包并且运行良好。
  • 不参与继承。
  • 您是否要求了解两者之间的所有差异?因为有不少。
  • 如果想要在短类中摆脱self.name = arg 模式,并且它们主要存储数据,请使用dataclass。否则,这样做会打破我认为的 Python 数据模型的许多假设。正如你可以从@MisterMiyagi 的回答中推断出来的那样。

标签: python python-3.x oop design-patterns


【解决方案1】:

方法对象在类及其子类的所有实例之间共享。为每个实例重新创建一个“__init__ 方法”对象。

方法使用与classmethods、staticmethods、propertys 或任何其他描述符相同的机制。 “__init__ 方法”使用自己独特的非标准协议。

方法可以遵循基类实现,并使用默认的 Method-Resolution-Order。 “__init__ 方法”需要自己的方法来访问其基本实现。

方法仅在需要时绑定到它们的实例。 “__init__ 方法”始终处于绑定状态。

方法具有可访问的限定名称;这使他们pickleable 和其他东西。 “__init__ 方法”没有可访问的限定名称,因为它在技术上是函数执行的本地。

方法定义了一个类及其所有实例的接口。 “__init__ 方法”仅定义其实例的接口,因为它在类中不可见。

方法使用一组属性,即实例属性。一个“__init__方法”使用了两个集合,即实例属性和__init__闭包。

元类工具可以访问方法,例如用于抽象子类实现。元类无法访问“__init__ 方法”。

方法可以与可调用属性区分开来。无法将“__init__ 方法”与可调用属性区分开来。

方法对特殊方法和常规方法使用相同的机制。 “__init__ 方法”无法实现特殊方法。

【讨论】:

    【解决方案2】:

    方法是一个类属性。通过在 __init__ 中定义 f 并将其分配给 instance 属性,您并没有定义实例方法,只是一个可调用的实例属性。

    class Foo2:
        def __init__(self, val):
            # self.val = val, no need that
            def f(arg=val):
                print(arg)
            self.f = f
    
    
    class Bar(Foo2):
        def f(self, arg):
            print("Not called")
    
    b = Bar(3)
    b.f()  # outputs 3, not "Not called"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-17
      • 2015-02-10
      • 2016-11-13
      • 1970-01-01
      • 2019-02-28
      • 2020-08-15
      • 1970-01-01
      相关资源
      最近更新 更多